Rev 1633 | Rev 2187 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1498 | serge | 1 | |
1625 | serge | 2 | #include |
3 | #include |
||
4 | #include |
||
5 | #include |
||
1498 | serge | 6 | |
7 | |||
8 | #include "acpi_bus.h" |
||
1627 | serge | 9 | #include "dmdev.h" |
1867 | serge | 10 | |
1498 | serge | 11 | |
1627 | serge | 12 | |
13 | |||
1625 | serge | 14 | #define ACPI_BUS_HID "KLBSYBUS" |
15 | #define ACPI_BUS_DEVICE_NAME "System Bus" |
||
16 | |||
17 | |||
18 | |||
19 | |||
20 | |||
1867 | serge | 21 | LIST_HEAD(acpi_bus_id_list); |
22 | LIST_HEAD(dmdev_tree); |
||
23 | |||
1625 | serge | 24 | |
1627 | serge | 25 | |
1625 | serge | 26 | { |
27 | char bus_id[15]; |
||
28 | unsigned int instance_no; |
||
29 | struct list_head node; |
||
30 | }; |
||
31 | |||
32 | |||
33 | |||
1498 | serge | 34 | #define ACPI_NS_SYSTEM_BUS "_SB_" |
35 | |||
36 | |||
37 | ACPI_IRQ_MODEL_PIC = 0, |
||
38 | ACPI_IRQ_MODEL_IOAPIC, |
||
39 | ACPI_IRQ_MODEL_IOSAPIC, |
||
40 | ACPI_IRQ_MODEL_PLATFORM, |
||
41 | ACPI_IRQ_MODEL_COUNT |
||
42 | }; |
||
43 | |||
44 | |||
1625 | serge | 45 | ACPI_BUS_REMOVAL_NORMAL = 0, |
46 | ACPI_BUS_REMOVAL_EJECT, |
||
47 | ACPI_BUS_REMOVAL_SUPRISE, |
||
48 | ACPI_BUS_REMOVAL_TYPE_COUNT |
||
49 | }; |
||
50 | |||
1498 | serge | 51 | |
1625 | serge | 52 | |
53 | #define PCI_MAX_PINS 4 |
||
54 | |||
55 | |||
56 | |||
57 | |||
58 | static ACPI_HANDLE pci_root_handle; |
||
59 | |||
60 | |||
61 | |||
1498 | serge | 62 | (addr_t)((addr_t)(addr) + (addr_t)(off)) |
63 | |||
64 | |||
65 | // (addr_t)((addr_t)(addr) + OS_BASE) |
||
66 | |||
67 | |||
68 | |||
69 | |||
1867 | serge | 70 | |
71 | |||
1633 | serge | 72 | |
1625 | serge | 73 | |
1633 | serge | 74 | |
1627 | serge | 75 | |
1625 | serge | 76 | |
1627 | serge | 77 | extern struct resource ioport_resource; |
78 | |||
1625 | serge | 79 | |
1627 | serge | 80 | { |
1625 | serge | 81 | IO_PIC = 0, |
1627 | serge | 82 | IO_APIC |
83 | }; |
||
1625 | serge | 84 | |
85 | |||
1867 | serge | 86 | resource_to_addr(ACPI_RESOURCE *resource, ACPI_RESOURCE_ADDRESS64 *addr); |
87 | |||
88 | |||
89 | |||
90 | |||
91 | |||
92 | |||
93 | |||
1627 | serge | 94 | { |
1625 | serge | 95 | ACPI_OBJECT arg1; |
1627 | serge | 96 | ACPI_OBJECT_LIST args; |
97 | ACPI_STATUS as; |
||
98 | |||
1625 | serge | 99 | |
1627 | serge | 100 | arg1.Integer.Value = mode; |
101 | args.Count = 1; |
||
102 | args.Pointer = &arg1; |
||
103 | |||
1625 | serge | 104 | |
1627 | serge | 105 | /* |
106 | * We can silently ignore failure as it may not be implemented, ACPI should |
||
107 | * provide us with correct information anyway |
||
108 | */ |
||
109 | if (ACPI_SUCCESS(as)) |
||
110 | dbgprintf(PREFIX "machine set to %s mode\n", mode ? "APIC" : "PIC"); |
||
111 | } |
||
1625 | serge | 112 | |
113 | |||
1498 | serge | 114 | |
115 | |||
116 | |||
117 | |||
1625 | serge | 118 | |
119 | |||
1627 | serge | 120 | |
1625 | serge | 121 | |
1627 | serge | 122 | |
1625 | serge | 123 | |
124 | |||
1633 | serge | 125 | |
1498 | serge | 126 | |
1627 | serge | 127 | #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" |
128 | |||
1498 | serge | 129 | |
1627 | serge | 130 | get_root_bridge_busnr_callback(ACPI_RESOURCE *resource, void *data) |
131 | { |
||
1625 | serge | 132 | struct resource *res = data; |
1627 | serge | 133 | ACPI_RESOURCE_ADDRESS64 address; |
134 | |||
1498 | serge | 135 | |
1627 | serge | 136 | resource->Type != ACPI_RESOURCE_TYPE_ADDRESS32 && |
137 | resource->Type != ACPI_RESOURCE_TYPE_ADDRESS64) |
||
138 | return AE_OK; |
||
1625 | serge | 139 | |
1498 | serge | 140 | |
1627 | serge | 141 | if ((address.AddressLength > 0) && |
142 | (address.ResourceType == ACPI_BUS_NUMBER_RANGE)) { |
||
143 | res->start = address.Minimum; |
||
144 | res->end = address.Minimum + address.AddressLength - 1; |
||
145 | } |
||
1625 | serge | 146 | |
1627 | serge | 147 | |
148 | } |
||
1625 | serge | 149 | |
1500 | serge | 150 | |
1625 | serge | 151 | |
152 | |||
1627 | serge | 153 | struct resource *res) |
154 | { |
||
1625 | serge | 155 | ACPI_STATUS status; |
156 | |||
157 | |||
1627 | serge | 158 | status = |
159 | AcpiWalkResources(handle, METHOD_NAME__CRS, |
||
160 | get_root_bridge_busnr_callback, res); |
||
161 | if (ACPI_FAILURE(status)) |
||
1625 | serge | 162 | return status; |
1627 | serge | 163 | if (res->start == -1) |
164 | return AE_ERROR; |
||
165 | return AE_OK; |
||
166 | } |
||
167 | |||
1498 | serge | 168 | |
169 | |||
1628 | serge | 170 | { |
171 | int status; |
||
172 | struct acpi_device *child = NULL; |
||
173 | |||
174 | |||
175 | if (device->parent && device->parent->ops.bind) { |
||
176 | status = device->parent->ops.bind(device); |
||
177 | if (!status) { |
||
178 | list_for_each_entry(child, &device->children, node) |
||
179 | acpi_pci_bridge_scan(child); |
||
180 | } |
||
181 | } |
||
182 | } |
||
183 | |||
184 | |||
185 | |||
186 | |||
1627 | serge | 187 | { |
188 | struct acpi_device *bridge; |
||
189 | char *name; |
||
190 | unsigned int res_num; |
||
191 | struct resource *res; |
||
192 | struct pci_bus *bus; |
||
193 | int busnum; |
||
194 | }; |
||
195 | |||
1625 | serge | 196 | |
1498 | serge | 197 | |
1627 | serge | 198 | resource_to_addr(ACPI_RESOURCE *resource, ACPI_RESOURCE_ADDRESS64 *addr) |
199 | { |
||
1498 | serge | 200 | ACPI_STATUS status; |
1625 | serge | 201 | struct acpi_resource_memory24 *memory24; |
1627 | serge | 202 | struct acpi_resource_memory32 *memory32; |
203 | struct acpi_resource_fixed_memory32 *fixed_memory32; |
||
204 | |||
1498 | serge | 205 | |
1627 | serge | 206 | switch (resource->Type) { |
207 | case ACPI_RESOURCE_TYPE_MEMORY24: |
||
208 | memory24 = &resource->Data.Memory24; |
||
209 | addr->ResourceType = ACPI_MEMORY_RANGE; |
||
210 | addr->Minimum = memory24->Minimum; |
||
211 | addr->AddressLength = memory24->AddressLength; |
||
212 | addr->Maximum = addr->Minimum + addr->AddressLength - 1; |
||
213 | return AE_OK; |
||
214 | case ACPI_RESOURCE_TYPE_MEMORY32: |
||
215 | memory32 = &resource->Data.Memory32; |
||
216 | addr->ResourceType = ACPI_MEMORY_RANGE; |
||
217 | addr->Minimum = memory32->Minimum; |
||
218 | addr->AddressLength = memory32->AddressLength; |
||
219 | addr->Maximum = addr->Minimum + addr->AddressLength - 1; |
||
220 | return AE_OK; |
||
221 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
||
222 | fixed_memory32 = &resource->Data.FixedMemory32; |
||
223 | addr->ResourceType = ACPI_MEMORY_RANGE; |
||
224 | addr->Minimum = fixed_memory32->Address; |
||
225 | addr->AddressLength = fixed_memory32->AddressLength; |
||
226 | addr->Maximum = addr->Minimum + addr->AddressLength - 1; |
||
227 | return AE_OK; |
||
228 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
||
229 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
||
230 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
||
231 | status = AcpiResourceToAddress64(resource, addr); |
||
232 | if (ACPI_SUCCESS(status) && |
||
233 | (addr->ResourceType == ACPI_MEMORY_RANGE || |
||
234 | addr->ResourceType == ACPI_IO_RANGE) && |
||
235 | addr->AddressLength > 0) { |
||
236 | return AE_OK; |
||
237 | } |
||
238 | break; |
||
239 | } |
||
240 | return AE_ERROR; |
||
241 | } |
||
1625 | serge | 242 | |
243 | |||
244 | |||
1627 | serge | 245 | count_resource(ACPI_RESOURCE *acpi_res, void *data) |
246 | { |
||
1625 | serge | 247 | struct pci_root_info *info = data; |
1627 | serge | 248 | ACPI_RESOURCE_ADDRESS64 addr; |
249 | ACPI_STATUS status; |
||
250 | |||
1625 | serge | 251 | |
1627 | serge | 252 | if (ACPI_SUCCESS(status)) |
253 | info->res_num++; |
||
254 | return AE_OK; |
||
255 | } |
||
1625 | serge | 256 | |
1498 | serge | 257 | |
258 | |||
1627 | serge | 259 | { |
1625 | serge | 260 | struct pci_root_info *info = data; |
1627 | serge | 261 | struct resource *res; |
262 | struct acpi_resource_address64 addr; |
||
263 | ACPI_STATUS status; |
||
264 | unsigned long flags; |
||
265 | struct resource *root, *conflict; |
||
266 | u64 start, end; |
||
267 | |||
1625 | serge | 268 | |
1627 | serge | 269 | if (!ACPI_SUCCESS(status)) |
270 | return AE_OK; |
||
271 | |||
1625 | serge | 272 | |
1627 | serge | 273 | { |
274 | root = &iomem_resource; |
||
275 | flags = IORESOURCE_MEM; |
||
276 | if (addr.Info.Mem.Caching == ACPI_PREFETCHABLE_MEMORY) |
||
277 | flags |= IORESOURCE_PREFETCH; |
||
278 | } |
||
1498 | serge | 279 | else if (addr.ResourceType == ACPI_IO_RANGE) |
1627 | serge | 280 | { |
281 | root = &ioport_resource; |
||
282 | flags = IORESOURCE_IO; |
||
283 | } else |
||
284 | return AE_OK; |
||
285 | |||
1625 | serge | 286 | |
1627 | serge | 287 | end = addr.Maximum + addr.TranslationOffset; |
288 | |||
1625 | serge | 289 | |
1627 | serge | 290 | res->name = info->name; |
291 | res->flags = flags; |
||
292 | res->start = start; |
||
293 | res->end = end; |
||
294 | res->child = NULL; |
||
295 | |||
1625 | serge | 296 | |
1627 | serge | 297 | printk("host bridge window %pR (ignored)\n", res); |
298 | return AE_OK; |
||
299 | } |
||
300 | |||
1625 | serge | 301 | |
1627 | serge | 302 | conflict = insert_resource_conflict(root, res); |
303 | if (conflict) { |
||
304 | dev_err(&info->bridge->dev, |
||
305 | "address space collision: host bridge window %pR " |
||
306 | "conflicts with %s %pR\n", |
||
307 | res, conflict->name, conflict); |
||
308 | } else { |
||
309 | pci_bus_add_resource(info->bus, res, 0); |
||
310 | info->res_num++; |
||
311 | if (addr.translation_offset) |
||
312 | dev_info(&info->bridge->dev, "host bridge window %pR " |
||
313 | "(PCI address [%#llx-%#llx])\n", |
||
314 | res, res->start - addr.translation_offset, |
||
315 | res->end - addr.translation_offset); |
||
316 | else |
||
317 | dev_info(&info->bridge->dev, |
||
318 | "host bridge window %pR\n", res); |
||
319 | } |
||
320 | return AE_OK; |
||
321 | #endif |
||
322 | } |
||
1498 | serge | 323 | |
324 | |||
325 | |||
1625 | serge | 326 | |
1627 | serge | 327 | get_current_resources(struct acpi_device *device, int busnum, |
328 | int domain, struct pci_bus *bus) |
||
329 | { |
||
1625 | serge | 330 | struct pci_root_info info; |
1627 | serge | 331 | size_t size; |
332 | |||
1625 | serge | 333 | |
1627 | serge | 334 | |
1625 | serge | 335 | |
1627 | serge | 336 | // pci_bus_remove_resources(bus); |
337 | |||
1625 | serge | 338 | |
1627 | serge | 339 | info.bus = bus; |
340 | info.res_num = 0; |
||
341 | AcpiWalkResources(device->handle, METHOD_NAME__CRS, count_resource, |
||
342 | &info); |
||
343 | if (!info.res_num) |
||
344 | return; |
||
345 | |||
1625 | serge | 346 | |
1627 | serge | 347 | info.res = kmalloc(size, GFP_KERNEL); |
348 | if (!info.res) |
||
349 | goto res_alloc_fail; |
||
350 | |||
1625 | serge | 351 | |
1627 | serge | 352 | info.name = strdup(buf); |
353 | |||
1625 | serge | 354 | |
1627 | serge | 355 | goto name_alloc_fail; |
356 | |||
1625 | serge | 357 | |
1627 | serge | 358 | AcpiWalkResources(device->handle, METHOD_NAME__CRS, setup_resource, |
359 | &info); |
||
360 | |||
1625 | serge | 361 | |
1627 | serge | 362 | |
1625 | serge | 363 | |
1627 | serge | 364 | kfree(info.res); |
365 | res_alloc_fail: |
||
366 | return; |
||
367 | } |
||
1625 | serge | 368 | |
369 | |||
370 | |||
371 | |||
372 | |||
1627 | serge | 373 | .read = NULL, |
374 | .write = NULL, |
||
375 | }; |
||
376 | |||
1625 | serge | 377 | |
378 | |||
1627 | serge | 379 | { |
1625 | serge | 380 | struct acpi_device *device = root->device; |
1627 | serge | 381 | int domain = root->segment; |
382 | int busnum = root->secondary.start; |
||
383 | struct pci_bus *bus; |
||
384 | struct pci_sysdata *sd; |
||
385 | int node = 0; |
||
386 | |||
1625 | serge | 387 | |
1627 | serge | 388 | printk(KERN_WARNING "pci_bus %04x:%02x: " |
389 | "ignored (multiple domains not supported)\n", |
||
390 | domain, busnum); |
||
391 | return NULL; |
||
392 | } |
||
1625 | serge | 393 | |
394 | |||
1627 | serge | 395 | * TODO: leak; this memory is never freed. |
396 | * It's arguable whether it's worth the trouble to care. |
||
397 | */ |
||
1625 | serge | 398 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); |
1627 | serge | 399 | if (!sd) { |
400 | printk(KERN_WARNING "pci_bus %04x:%02x: " |
||
401 | "ignored (out of memory)\n", domain, busnum); |
||
402 | return NULL; |
||
403 | } |
||
1625 | serge | 404 | |
405 | |||
1627 | serge | 406 | sd->node = node; |
407 | /* |
||
1625 | serge | 408 | * Maybe the desired pci bus has been already scanned. In such case |
1627 | serge | 409 | * it is unnecessary to scan the pci bus with the given domain,busnum. |
410 | */ |
||
1625 | serge | 411 | bus = pci_find_bus(domain, busnum); |
1627 | serge | 412 | if (bus) { |
413 | /* |
||
414 | * If the desired bus exits, the content of bus->sysdata will |
||
415 | * be replaced by sd. |
||
416 | */ |
||
417 | memcpy(bus->sysdata, sd, sizeof(*sd)); |
||
418 | kfree(sd); |
||
419 | } else { |
||
420 | bus = pci_create_bus(busnum, &pci_root_ops, sd); |
||
421 | if (bus) { |
||
422 | get_current_resources(device, busnum, domain, bus); |
||
423 | bus->subordinate = pci_scan_child_bus(bus); |
||
1628 | serge | 424 | } |
1625 | serge | 425 | } |
426 | |||
427 | |||
1627 | serge | 428 | kfree(sd); |
429 | |||
1625 | serge | 430 | |
1627 | serge | 431 | printk("on NUMA node %d\n", node); |
432 | } |
||
433 | |||
1625 | serge | 434 | |
1627 | serge | 435 | } |
1625 | serge | 436 | |
437 | |||
438 | |||
439 | |||
1627 | serge | 440 | { |
1625 | serge | 441 | unsigned long long segment, bus; |
1627 | serge | 442 | ACPI_STATUS status; |
443 | int result; |
||
1625 | serge | 444 | struct acpi_pci_root *root; |
1627 | serge | 445 | ACPI_HANDLE handle; |
446 | struct acpi_device *child; |
||
447 | u32 flags, base_flags; |
||
448 | |||
1625 | serge | 449 | |
1627 | serge | 450 | if (!root) |
451 | return -ENOMEM; |
||
1625 | serge | 452 | |
1627 | serge | 453 | |
454 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, |
||
455 | &segment); |
||
456 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
||
457 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); |
||
458 | result = -ENODEV; |
||
459 | goto end; |
||
460 | } |
||
1625 | serge | 461 | |
462 | |||
1627 | serge | 463 | root->secondary.flags = IORESOURCE_BUS; |
464 | status = try_get_root_bridge_busnr(device->handle, &root->secondary); |
||
465 | if (ACPI_FAILURE(status)) |
||
466 | { |
||
467 | /* |
||
468 | * We need both the start and end of the downstream bus range |
||
469 | * to interpret _CBA (MMCONFIG base address), so it really is |
||
470 | * supposed to be in _CRS. If we don't find it there, all we |
||
471 | * can do is assume [_BBN-0xFF] or [0-0xFF]. |
||
472 | */ |
||
473 | root->secondary.end = 0xFF; |
||
474 | printk(KERN_WARNING PREFIX |
||
475 | "no secondary bus range in _CRS\n"); |
||
476 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); |
||
477 | if (ACPI_SUCCESS(status)) |
||
478 | root->secondary.start = bus; |
||
479 | else if (status == AE_NOT_FOUND) |
||
480 | root->secondary.start = 0; |
||
481 | else { |
||
482 | printk(KERN_ERR PREFIX "can't evaluate _BBN\n"); |
||
483 | result = -ENODEV; |
||
484 | goto end; |
||
485 | } |
||
486 | } |
||
487 | |||
1625 | serge | 488 | |
1627 | serge | 489 | root->device = device; |
490 | root->segment = segment & 0xFFFF; |
||
491 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
||
492 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
||
493 | device->driver_data = root; |
||
494 | |||
1625 | serge | 495 | |
496 | * All supported architectures that use ACPI have support for |
||
1627 | serge | 497 | * PCI domains, so we indicate this in _OSC support capabilities. |
498 | */ |
||
1625 | serge | 499 | // flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
1627 | serge | 500 | // acpi_pci_osc_support(root, flags); |
501 | |||
1625 | serge | 502 | |
503 | * TBD: Need PCI interface for enumeration/configuration of roots. |
||
1627 | serge | 504 | */ |
1625 | serge | 505 | |
506 | |||
1627 | serge | 507 | list_add_tail(&root->node, &acpi_pci_roots); |
508 | |||
1625 | serge | 509 | |
1627 | serge | 510 | acpi_device_name(device), acpi_device_bid(device), |
511 | root->segment, &root->secondary); |
||
512 | |||
1625 | serge | 513 | |
514 | * Scan the Root Bridge |
||
1627 | serge | 515 | * -------------------- |
516 | * Must do this prior to any attempt to bind the root device, as the |
||
517 | * PCI namespace does not get created until this call is made (and |
||
518 | * thus the root bridge's pci_dev does not exist). |
||
519 | */ |
||
1625 | serge | 520 | |
521 | |||
1627 | serge | 522 | if (!root->bus) { |
523 | printk(KERN_ERR PREFIX |
||
524 | "Bus %04x:%02x not present in PCI namespace\n", |
||
525 | root->segment, (unsigned int)root->secondary.start); |
||
526 | result = -ENODEV; |
||
527 | goto end; |
||
528 | } |
||
529 | |||
1625 | serge | 530 | |
1627 | serge | 531 | * Attach ACPI-PCI Context |
532 | * ----------------------- |
||
533 | * Thus binding the ACPI and PCI devices. |
||
534 | */ |
||
535 | result = acpi_pci_bind_root(device); |
||
1628 | serge | 536 | if (result) |
537 | goto end; |
||
538 | |||
1625 | serge | 539 | |
540 | * PCI Routing Table |
||
1627 | serge | 541 | * ----------------- |
542 | * Evaluate and parse _PRT, if exists. |
||
543 | */ |
||
1625 | serge | 544 | status = AcpiGetHandle(device->handle, METHOD_NAME__PRT, &handle); |
1627 | serge | 545 | if (ACPI_SUCCESS(status)) |
1625 | serge | 546 | result = acpi_pci_irq_add_prt(device->handle, root->bus); |
1627 | serge | 547 | |
1625 | serge | 548 | |
1627 | serge | 549 | * Scan and bind all _ADR-Based Devices |
550 | */ |
||
551 | list_for_each_entry(child, &device->children, node) |
||
1628 | serge | 552 | acpi_pci_bridge_scan(child); |
553 | |||
1625 | serge | 554 | |
1627 | serge | 555 | |
1625 | serge | 556 | |
1627 | serge | 557 | if (!list_empty(&root->node)) |
558 | list_del(&root->node); |
||
559 | kfree(root); |
||
560 | return result; |
||
561 | } |
||
1625 | serge | 562 | |
563 | |||
564 | |||
1627 | serge | 565 | { |
1625 | serge | 566 | {"PNP0A03", 0}, |
1627 | serge | 567 | {"", 0}, |
568 | }; |
||
1625 | serge | 569 | |
570 | |||
1627 | serge | 571 | { |
1625 | serge | 572 | struct acpi_device *child; |
573 | |||
574 | |||
1627 | serge | 575 | { |
576 | dbgprintf(PREFIX "PCI root %s\n", device->pnp.bus_id); |
||
577 | acpi_pci_root_add(device); |
||
578 | }; |
||
579 | |||
1625 | serge | 580 | |
581 | { |
||
582 | acpi_init_pci(child); |
||
1627 | serge | 583 | }; |
1625 | serge | 584 | |
1627 | serge | 585 | |
1625 | serge | 586 | |
587 | |||
1627 | serge | 588 | |
1498 | serge | 589 | { |
590 | u32_t retval; |
||
591 | |||
592 | |||
1500 | serge | 593 | |
594 | |||
1498 | serge | 595 | |
596 | |||
597 | return 0; |
||
598 | |||
599 | |||
1625 | serge | 600 | { |
601 | printf("Can't open /rd/1/drivers/acpi.log\nExit\n"); |
||
602 | return 0; |
||
603 | } |
||
604 | |||
605 | |||
1500 | serge | 606 | if (ACPI_FAILURE(status)) { |
607 | dbgprintf("Unable to reallocate ACPI tables\n"); |
||
608 | goto err; |
||
609 | } |
||
610 | |||
1498 | serge | 611 | |
1500 | serge | 612 | if (status != AE_OK) { |
613 | dbgprintf("AcpiInitializeSubsystem failed (%s)\n", |
||
614 | AcpiFormatException(status)); |
||
615 | goto err; |
||
616 | } |
||
617 | |||
1498 | serge | 618 | |
1500 | serge | 619 | if (status != AE_OK) { |
620 | dbgprintf("AcpiInitializeTables failed (%s)\n", |
||
621 | AcpiFormatException(status)); |
||
622 | goto err; |
||
623 | } |
||
624 | |||
1498 | serge | 625 | |
1500 | serge | 626 | if (status != AE_OK) { |
627 | dbgprintf("AcpiLoadTables failed (%s)\n", |
||
628 | AcpiFormatException(status)); |
||
629 | goto err; |
||
630 | } |
||
631 | |||
1498 | serge | 632 | |
1625 | serge | 633 | |
1498 | serge | 634 | |
1625 | serge | 635 | if (status != AE_OK) { |
1498 | serge | 636 | dbgprintf("AcpiEnableSubsystem failed (%s)\n", |
637 | AcpiFormatException(status)); |
||
638 | goto err; |
||
639 | } |
||
640 | |||
641 | |||
1625 | serge | 642 | if (ACPI_FAILURE (status)) |
1498 | serge | 643 | { |
644 | dbgprintf("AcpiInitializeObjects failed (%s)\n", |
||
645 | AcpiFormatException(status)); |
||
646 | goto err; |
||
647 | } |
||
648 | |||
649 | |||
1625 | serge | 650 | |
651 | |||
652 | |||
1627 | serge | 653 | |
1625 | serge | 654 | |
1627 | serge | 655 | |
1625 | serge | 656 | |
1633 | serge | 657 | |
658 | |||
1867 | serge | 659 | |
1625 | serge | 660 | |
1867 | serge | 661 | |
1625 | serge | 662 | |
1867 | serge | 663 | |
1625 | serge | 664 | |
1867 | serge | 665 | |
1498 | serge | 666 | |
1867 | serge | 667 | |
1498 | serge | 668 | |
1867 | serge | 669 | { |
670 | size_t len = strlen (str) + 1; |
||
671 | char *copy = malloc(len); |
||
672 | if (copy) |
||
673 | { |
||
674 | memcpy (copy, str, len); |
||
675 | } |
||
1498 | serge | 676 | return copy; |
1867 | serge | 677 | } |
678 | |||
1498 | serge | 679 | |
680 | |||
1867 | serge | 681 | { |
682 | struct pci_bus *tbus; |
||
683 | struct pci_dev *dev; |
||
684 | dmdev_t *dmdev; |
||
685 | |||
1498 | serge | 686 | |
1867 | serge | 687 | |
1498 | serge | 688 | |
1867 | serge | 689 | // dmdev->type = 1; |
690 | // dmdev->acpi_dev = bus->self->acpi_dev; |
||
691 | // dmdev->pci_dev = bus->self; |
||
692 | // list_add_tail(&dmdev->list, &dmdev_tree); |
||
693 | |||
1498 | serge | 694 | |
1867 | serge | 695 | { |
696 | dmdev = (dmdev_t*)kzalloc(sizeof(dmdev_t),GFP_KERNEL); |
||
697 | |||
1498 | serge | 698 | |
1867 | serge | 699 | dmdev->type = 1; |
700 | dmdev->acpi_dev = dev->acpi_dev; |
||
701 | dmdev->pci_dev = dev; |
||
702 | list_add_tail(&dmdev->list, &dmdev_tree); |
||
703 | }; |
||
704 | |||
1498 | serge | 705 | |
1867 | serge | 706 | { |
707 | dm_add_pci_bus(tbus); |
||
708 | }; |
||
709 | |||
1498 | serge | 710 | |
1867 | serge | 711 | |
1498 | serge | 712 | |
1867 | serge | 713 | count_dev_resources(ACPI_RESOURCE *acpi_res, void *data) |
714 | { |
||
715 | (*(int*)data)++; |
||
716 | return AE_OK; |
||
717 | } |
||
718 | |||
1498 | serge | 719 | |
720 | |||
1867 | serge | 721 | { |
1625 | serge | 722 | struct acpi_device *child; |
1867 | serge | 723 | ACPI_DEVICE_INFO *info = NULL; |
724 | ACPI_STATUS status; |
||
1625 | serge | 725 | |
726 | |||
1867 | serge | 727 | uint32_t res_num = 0; |
728 | |||
1625 | serge | 729 | |
1867 | serge | 730 | |
1625 | serge | 731 | |
1867 | serge | 732 | { |
733 | if( strcmp(info->HardwareId.String,"PNP0C0F") == 0) |
||
734 | { |
||
735 | kfree(info); |
||
736 | return; |
||
737 | }; |
||
738 | }; |
||
739 | |||
1625 | serge | 740 | |
1867 | serge | 741 | |
1625 | serge | 742 | |
1867 | serge | 743 | { |
744 | AcpiWalkResources(device->handle, METHOD_NAME__CRS, |
||
745 | count_dev_resources, &res_num); |
||
746 | |||
1625 | serge | 747 | |
1867 | serge | 748 | { |
749 | dmdev = (dmdev_t*)kzalloc(sizeof(dmdev_t),GFP_KERNEL); |
||
750 | |||
1625 | serge | 751 | |
1867 | serge | 752 | dmdev->type = 0; |
753 | dmdev->acpi_dev = device; |
||
754 | dmdev->pci_dev = NULL; |
||
755 | list_add_tail(&dmdev->list, &dmdev_tree); |
||
756 | }; |
||
757 | }; |
||
758 | list_for_each_entry(child, &device->children, node) |
||
759 | { |
||
1625 | serge | 760 | dm_add_acpi(child); |
1867 | serge | 761 | }; |
1625 | serge | 762 | }; |
1867 | serge | 763 | |
1625 | serge | 764 | |
1867 | serge | 765 | { |
1625 | serge | 766 | struct acpi_pci_root *root; |
1867 | serge | 767 | |
1625 | serge | 768 | |
769 | |||
1867 | serge | 770 | { |
1625 | serge | 771 | struct pci_bus *pbus, *tbus; |
1867 | serge | 772 | struct pci_dev *dev; |
773 | |||
1625 | serge | 774 | |
1867 | serge | 775 | |
1625 | serge | 776 | |
1867 | serge | 777 | }; |
778 | |||
1625 | serge | 779 | |
1867 | serge | 780 | }; |
781 | |||
1625 | serge | 782 | |
1867 | serge | 783 | { |
1625 | serge | 784 | if(res->flags !=0 ) |
1867 | serge | 785 | { |
786 | if(res->flags & IORESOURCE_IO) |
||
787 | dbgprintf(" IO range "); |
||
788 | else if(res->flags & IORESOURCE_MEM) |
||
789 | dbgprintf(" MMIO range "); |
||
790 | dbgprintf("%x - %x\n", res->start, res->end); |
||
791 | }; |
||
792 | }; |
||
793 | |||
1625 | serge | 794 | |
1867 | serge | 795 | print_acpi_resource(ACPI_RESOURCE *acpi_res, void *data) |
796 | { |
||
1625 | serge | 797 | ACPI_RESOURCE_ADDRESS64 addr; |
1867 | serge | 798 | ACPI_STATUS status; |
799 | int i; |
||
800 | |||
1625 | serge | 801 | |
1867 | serge | 802 | { |
1625 | serge | 803 | case ACPI_RESOURCE_TYPE_IRQ: |
1867 | serge | 804 | { |
805 | ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*)&acpi_res->Data; |
||
806 | dbgprintf(" IRQ %d\n", irq_data->Interrupts[0]); |
||
807 | }; |
||
808 | break; |
||
809 | |||
1625 | serge | 810 | |
1867 | serge | 811 | { |
812 | ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*)&acpi_res->Data; |
||
813 | dbgprintf(" IRQ %d\n", irq_data->Interrupts[0]); |
||
814 | }; |
||
815 | break; |
||
816 | |||
1625 | serge | 817 | |
1867 | serge | 818 | { |
819 | ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &acpi_res->Data; |
||
820 | for(i=0; i < dma_data->ChannelCount; i++) |
||
821 | { |
||
822 | dbgprintf(" DMA %s channel %d\n", |
||
823 | dma_data->Type == ACPI_TYPE_A ? "Type A": |
||
824 | dma_data->Type == ACPI_TYPE_B ? "Type B" : |
||
825 | dma_data->Type == ACPI_TYPE_F ? "Type F" : "", |
||
826 | dma_data->Channels[i]); |
||
827 | } |
||
828 | }; |
||
829 | break; |
||
830 | |||
1625 | serge | 831 | |
1867 | serge | 832 | { |
833 | ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &acpi_res->Data; |
||
834 | |||
1625 | serge | 835 | |
1867 | serge | 836 | io_data->Minimum+io_data->AddressLength-1); |
837 | } |
||
838 | break; |
||
839 | |||
1625 | serge | 840 | |
1867 | serge | 841 | { |
842 | ACPI_RESOURCE_FIXED_IO *io_data = (ACPI_RESOURCE_FIXED_IO*) &acpi_res->Data; |
||
843 | dbgprintf(" Fixed IO range 0%x-0%x\n",io_data->Address, |
||
844 | io_data->Address+io_data->AddressLength-1); |
||
845 | }; |
||
846 | break; |
||
847 | |||
1625 | serge | 848 | |
1867 | serge | 849 | case ACPI_RESOURCE_TYPE_MEMORY32: |
850 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
||
851 | { |
||
852 | ACPI_RESOURCE_ADDRESS64 addr64; |
||
853 | resource_to_addr(acpi_res, &addr64); |
||
854 | dbgprintf(" Memory range 0%x-0%x\n", |
||
855 | (uint32_t)addr64.Minimum, (uint32_t)addr64.Maximum); |
||
856 | } |
||
857 | break; |
||
858 | |||
1625 | serge | 859 | |
1867 | serge | 860 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
861 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
||
862 | { |
||
863 | ACPI_RESOURCE_ADDRESS64 addr64; |
||
864 | ACPI_STATUS status; |
||
865 | |||
1625 | serge | 866 | |
1867 | serge | 867 | if (ACPI_SUCCESS(status)) |
868 | { |
||
869 | dbgprintf(" Address range 0%x-0%x\n", |
||
870 | (uint32_t)addr64.Minimum, (uint32_t)addr64.Maximum); |
||
871 | } |
||
872 | }; |
||
873 | break; |
||
874 | }; |
||
875 | |||
1625 | serge | 876 | |
877 | }; |
||
1867 | serge | 878 | |
1625 | serge | 879 | |
880 | |||
1867 | serge | 881 | { |
1625 | serge | 882 | struct pci_dev *pcidev; |
1867 | serge | 883 | struct acpi_device *acpidev; |
884 | dmdev_t *dmdev; |
||
885 | uint32_t i; |
||
886 | |||
1625 | serge | 887 | |
1867 | serge | 888 | |
1625 | serge | 889 | |
1867 | serge | 890 | { |
891 | switch(dmdev->type) |
||
892 | { |
||
893 | case 0: |
||
894 | if(dmdev->acpi_dev != NULL) |
||
895 | { |
||
896 | acpidev = dmdev->acpi_dev; |
||
897 | dbgprintf("\n%s\n", acpidev->pnp.bus_id); |
||
898 | AcpiWalkResources(acpidev->handle, METHOD_NAME__CRS, |
||
899 | print_acpi_resource, NULL); |
||
900 | }; |
||
901 | break; |
||
902 | |||
1625 | serge | 903 | |
1867 | serge | 904 | if(dmdev->pci_dev != NULL) |
905 | { |
||
906 | pcidev = dmdev->pci_dev; |
||
907 | dbgprintf("\nPCI_%x_%x bus:%d devfn: %x\n", |
||
908 | pcidev->vendor, pcidev->device, |
||
909 | pcidev->busnr, pcidev->devfn); |
||
910 | |||
1625 | serge | 911 | |
1867 | serge | 912 | print_pci_resource(&pcidev->resource[i]); |
913 | |||
1625 | serge | 914 | |
1867 | serge | 915 | dbgprintf(" APIC IRQ: %d\n", acpi_get_irq(pcidev)); |
916 | }; |
||
917 | break; |
||
918 | }; |
||
919 | }; |
||
920 | };>> |
||
921 |