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