7,6 → 7,7 |
|
#include "acpi.h" |
#include "acpi_bus.h" |
#include "dmdev.h" |
|
#define PREFIX "ACPI: " |
|
17,8 → 18,9 |
|
#define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
|
static LIST_HEAD(acpi_device_list); |
static LIST_HEAD(acpi_bus_id_list); |
LIST_HEAD(acpi_device_list); |
LIST_HEAD(acpi_bus_id_list); |
LIST_HEAD(dmdev_tree); |
|
|
struct acpi_device_bus_id |
65,6 → 67,8 |
|
#define acpi_remap( addr ) MapIoMem((void*)(addr),4096, 0x01) |
|
char* strdup(const char *str); |
|
void print_pci_irqs(); |
|
|
79,6 → 83,14 |
IO_APIC |
}; |
|
static ACPI_STATUS |
resource_to_addr(ACPI_RESOURCE *resource, ACPI_RESOURCE_ADDRESS64 *addr); |
|
static void create_dm_list(); |
|
static void print_dm_list(); |
|
|
static void set_pic_mode(enum pic_mode mode) |
{ |
ACPI_OBJECT arg1; |
99,17 → 111,8 |
dbgprintf(PREFIX "machine set to %s mode\n", mode ? "APIC" : "PIC"); |
} |
|
void print_device_tree(struct acpi_device *device) |
{ |
struct acpi_device *child; |
|
dbgprintf("%s\n", device->pnp.bus_id); |
|
list_for_each_entry(child, &device->children, node) |
{ |
print_device_tree(child); |
}; |
}; |
|
|
|
649,327 → 652,272 |
|
acpi_scan(); |
|
// print_device_tree(acpi_root); |
|
acpi_init_pci(acpi_root); |
|
print_pci_irqs(); |
|
/* |
ACPI_HANDLE bus_handle; |
ACPI_HANDLE pci_root; |
create_dm_list(); |
|
status = AcpiGetHandle(0, "\\_SB_", &bus_handle); |
dbgprintf("system bus handle %x\n", bus_handle); |
print_dm_list(); |
|
status = AcpiGetHandle(bus_handle, "PCI0", &pci_root); |
if (status != AE_OK) { |
dbgprintf("AcpiGetHandle failed (%s)\n", |
AcpiFormatException(status)); |
goto err; |
} |
err: |
|
AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 100, |
get_device_by_hid_callback, NULL, NULL, NULL); |
*/ |
return 0; |
|
#if 0 |
}; |
|
AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 4, |
get_device_by_hid_callback, NULL, NULL, NULL); |
|
ACPI_OBJECT obj; |
ACPI_HANDLE bus_handle; |
ACPI_HANDLE pci_root; |
|
status = AcpiGetHandle(0, "\\_SB_", &bus_handle); |
dbgprintf("system bus handle %x\n", bus_handle); |
|
status = AcpiGetHandle(bus_handle, "PCI0", &pci_root); |
|
if (status != AE_OK) { |
dbgprintf("AcpiGetHandle failed (%s)\n", |
AcpiFormatException(status)); |
goto err; |
char* strdup(const char *str) |
{ |
size_t len = strlen (str) + 1; |
char *copy = malloc(len); |
if (copy) |
{ |
memcpy (copy, str, len); |
} |
return copy; |
} |
|
dbgprintf("pci root handle %x\n\n", pci_root); |
|
ACPI_BUFFER prt_buffer; |
static void dm_add_pci_bus(struct pci_bus *bus) |
{ |
struct pci_bus *tbus; |
struct pci_dev *dev; |
dmdev_t *dmdev; |
|
prt_buffer.Length = ACPI_ALLOCATE_BUFFER; |
prt_buffer.Pointer = NULL; |
dmdev = (dmdev_t*)kzalloc(sizeof(dmdev_t),GFP_KERNEL); |
|
status = AcpiGetIrqRoutingTable(pci_root, &prt_buffer); |
// INIT_LIST_HEAD(&dmdev->list); |
// dmdev->type = 1; |
// dmdev->acpi_dev = bus->self->acpi_dev; |
// dmdev->pci_dev = bus->self; |
// list_add_tail(&dmdev->list, &dmdev_tree); |
|
if (status != AE_OK) { |
dbgprintf("AcpiGetIrqRoutingTable failed (%s)\n", |
AcpiFormatException(status)); |
goto err; |
} |
list_for_each_entry(dev, &bus->devices, bus_list) |
{ |
dmdev = (dmdev_t*)kzalloc(sizeof(dmdev_t),GFP_KERNEL); |
|
prt_walk_table(&prt_buffer); |
INIT_LIST_HEAD(&dmdev->list); |
dmdev->type = 1; |
dmdev->acpi_dev = dev->acpi_dev; |
dmdev->pci_dev = dev; |
list_add_tail(&dmdev->list, &dmdev_tree); |
}; |
|
list_for_each_entry(tbus, &bus->children, node) |
{ |
dm_add_pci_bus(tbus); |
}; |
|
ACPI_OBJECT arg = { ACPI_TYPE_INTEGER }; |
ACPI_OBJECT_LIST arg_list = { 1, &arg }; |
}; |
|
arg.Integer.Value = ACPI_IRQ_MODEL_IOAPIC; |
|
dbgprintf("\nset ioapic mode\n\n"); |
|
status = AcpiEvaluateObject(NULL, "\\_PIC", &arg_list, NULL); |
|
if (ACPI_FAILURE(status)) { |
dbgprintf("AcpiEvaluateObject failed (%s)\n", |
AcpiFormatException(status)); |
// goto err; |
static ACPI_STATUS |
count_dev_resources(ACPI_RESOURCE *acpi_res, void *data) |
{ |
(*(int*)data)++; |
return AE_OK; |
} |
|
|
status = AcpiGetIrqRoutingTable(pci_root, &prt_buffer); |
static void dm_add_acpi(struct acpi_device *device) |
{ |
struct acpi_device *child; |
ACPI_DEVICE_INFO *info = NULL; |
ACPI_STATUS status; |
|
if (status != AE_OK) { |
dbgprintf("AcpiGetIrqRoutingTable failed (%s)\n", |
AcpiFormatException(status)); |
goto err; |
} |
dmdev_t *dmdev; |
uint32_t res_num = 0; |
|
prt_walk_table(&prt_buffer); |
status = AcpiGetObjectInfo(device->handle, &info); |
|
u8_t pin = PciRead8 (0, (31<<3) | 1, 0x3D); |
dbgprintf("bus 0 device 31 function 1 pin %d\n", pin-1); |
if ( (status == AE_OK) && (info->Valid & ACPI_VALID_HID)) |
{ |
if( strcmp(info->HardwareId.String,"PNP0C0F") == 0) |
{ |
kfree(info); |
return; |
}; |
}; |
|
pin = PciRead8 (0, (31<<3) | 2, 0x3D); |
dbgprintf("bus 0 device 31 function 2 pin %d\n", pin-1); |
kfree(info); |
|
pin = PciRead8 (0, (31<<3) | 3, 0x3D); |
dbgprintf("bus 0 device 31 function 3 pin %d\n", pin-1); |
if(device->pci_dev == NULL) |
{ |
AcpiWalkResources(device->handle, METHOD_NAME__CRS, |
count_dev_resources, &res_num); |
|
pin = PciRead8 (0, (31<<3) | 4, 0x3D); |
dbgprintf("bus 0 device 31 function 4 pin %d\n", pin-1); |
if(res_num != 0) |
{ |
dmdev = (dmdev_t*)kzalloc(sizeof(dmdev_t),GFP_KERNEL); |
|
pin = PciRead8 (0, (31<<3) | 5, 0x3D); |
dbgprintf("bus 0 device 31 function 5 pin %d\n", pin-1); |
INIT_LIST_HEAD(&dmdev->list); |
dmdev->type = 0; |
dmdev->acpi_dev = device; |
dmdev->pci_dev = NULL; |
list_add_tail(&dmdev->list, &dmdev_tree); |
}; |
}; |
list_for_each_entry(child, &device->children, node) |
{ |
dm_add_acpi(child); |
}; |
}; |
|
pin = PciRead8 (0, (31<<3) | 6, 0x3D); |
dbgprintf("bus 0 device 31 function 6 pin %d\n", pin-1); |
static void create_dm_list() |
{ |
struct acpi_pci_root *root; |
|
pin = PciRead8 (0, (31<<3) | 7, 0x3D); |
dbgprintf("bus 0 device 31 function 7 pin %d\n", pin-1); |
#endif |
|
err: |
list_for_each_entry(root, &acpi_pci_roots, node) |
{ |
struct pci_bus *pbus, *tbus; |
struct pci_dev *dev; |
|
return 0; |
pbus = root->bus; |
|
dm_add_pci_bus(pbus); |
}; |
|
#if 0 |
dm_add_acpi(acpi_root); |
}; |
|
ACPI_STATUS |
get_device_by_hid_callback(ACPI_HANDLE obj, u32_t depth, void* context, |
void** retval) |
static void print_pci_resource(struct resource *res) |
{ |
static u32_t counter = 0; |
static char buff[256]; |
if(res->flags !=0 ) |
{ |
if(res->flags & IORESOURCE_IO) |
dbgprintf(" IO range "); |
else if(res->flags & IORESOURCE_MEM) |
dbgprintf(" MMIO range "); |
dbgprintf("%x - %x\n", res->start, res->end); |
}; |
}; |
|
static ACPI_STATUS |
print_acpi_resource(ACPI_RESOURCE *acpi_res, void *data) |
{ |
ACPI_RESOURCE_ADDRESS64 addr; |
ACPI_STATUS status; |
int i; |
|
ACPI_BUFFER buffer; |
|
ACPI_DEVICE_INFO *info; |
|
// *retval = NULL; |
|
buffer.Length = 255; |
buffer.Pointer = buff; |
|
status = AcpiGetName(obj, ACPI_FULL_PATHNAME, &buffer); |
if (status != AE_OK) { |
return AE_CTRL_TERMINATE; |
} |
|
buff[buffer.Length] = '\0'; |
|
dbgprintf("device %d %s ", counter, buff); |
|
status = AcpiGetObjectInfo(obj, &info); |
|
if (ACPI_SUCCESS (status)) |
switch (acpi_res->Type) |
{ |
if (info->Valid & ACPI_VALID_HID) |
dbgprintf (" HID: %s", info->HardwareId.String); |
|
case ACPI_RESOURCE_TYPE_IRQ: |
{ |
ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ*)&acpi_res->Data; |
dbgprintf(" IRQ %d\n", irq_data->Interrupts[0]); |
}; |
break; |
|
dbgprintf("\n"); |
counter++; |
|
return AE_OK; |
} |
|
prt_walk_table(ACPI_BUFFER *prt) |
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
{ |
ACPI_PCI_ROUTING_TABLE *entry; |
char *prtptr; |
ACPI_RESOURCE_EXTENDED_IRQ *irq_data = (ACPI_RESOURCE_EXTENDED_IRQ*)&acpi_res->Data; |
dbgprintf(" IRQ %d\n", irq_data->Interrupts[0]); |
}; |
break; |
|
/* First check to see if there is a table to walk. */ |
if (prt == NULL || prt->Pointer == NULL) |
return; |
|
/* Walk the table executing the handler function for each entry. */ |
prtptr = prt->Pointer; |
entry = (ACPI_PCI_ROUTING_TABLE *)prtptr; |
while (entry->Length != 0) |
case ACPI_RESOURCE_TYPE_DMA: |
{ |
|
dbgprintf("adress: %x %x ", (u32_t)(entry->Address>>32), |
(u32_t)entry->Address); |
dbgprintf("pin: %d index: %d source: %s\n", |
entry->Pin, |
entry->SourceIndex, |
entry->Source); |
|
// handler(entry, arg); |
prtptr += entry->Length; |
entry = (ACPI_PCI_ROUTING_TABLE *)prtptr; |
ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA*) &acpi_res->Data; |
for(i=0; i < dma_data->ChannelCount; i++) |
{ |
dbgprintf(" DMA %s channel %d\n", |
dma_data->Type == ACPI_TYPE_A ? "Type A": |
dma_data->Type == ACPI_TYPE_B ? "Type B" : |
dma_data->Type == ACPI_TYPE_F ? "Type F" : "", |
dma_data->Channels[i]); |
} |
} |
}; |
break; |
|
|
static void add_irq(unsigned dev, unsigned pin, u8_t irq) |
case ACPI_RESOURCE_TYPE_IO: |
{ |
// assert(dev < PCI_MAX_DEVICES && pin < PCI_MAX_PINS); |
ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO*) &acpi_res->Data; |
|
irqtable[dev * PCI_MAX_PINS + pin] = irq; |
dbgprintf(" IO range 0%x-0%x\n",io_data->Minimum, |
io_data->Minimum+io_data->AddressLength-1); |
} |
break; |
|
static ACPI_STATUS get_irq_resource(ACPI_RESOURCE *res, void *context) |
case ACPI_RESOURCE_TYPE_FIXED_IO: |
{ |
ACPI_PCI_ROUTING_TABLE *tbl = (ACPI_PCI_ROUTING_TABLE *) context; |
ACPI_RESOURCE_FIXED_IO *io_data = (ACPI_RESOURCE_FIXED_IO*) &acpi_res->Data; |
dbgprintf(" Fixed IO range 0%x-0%x\n",io_data->Address, |
io_data->Address+io_data->AddressLength-1); |
}; |
break; |
|
if (res->Type == ACPI_RESOURCE_TYPE_IRQ) |
case ACPI_RESOURCE_TYPE_MEMORY24: |
case ACPI_RESOURCE_TYPE_MEMORY32: |
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
{ |
ACPI_RESOURCE_IRQ *irq; |
|
irq = &res->Data.Irq; |
add_irq(tbl->Address >> 16, tbl->Pin, |
irq->Interrupts[tbl->SourceIndex]); |
} else if (res->Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) |
{ |
ACPI_RESOURCE_EXTENDED_IRQ *irq; |
|
add_irq(tbl->Address >> 16, tbl->Pin, |
irq->Interrupts[tbl->SourceIndex]); |
ACPI_RESOURCE_ADDRESS64 addr64; |
resource_to_addr(acpi_res, &addr64); |
dbgprintf(" Memory range 0%x-0%x\n", |
(uint32_t)addr64.Minimum, (uint32_t)addr64.Maximum); |
} |
break; |
|
return AE_OK; |
} |
|
char buff[4096]; |
|
static ACPI_STATUS get_pci_irq_routing(ACPI_HANDLE handle) |
case ACPI_RESOURCE_TYPE_ADDRESS16: |
case ACPI_RESOURCE_TYPE_ADDRESS32: |
case ACPI_RESOURCE_TYPE_ADDRESS64: |
{ |
ACPI_RESOURCE_ADDRESS64 addr64; |
ACPI_STATUS status; |
ACPI_BUFFER abuff; |
ACPI_PCI_ROUTING_TABLE *tbl; |
|
abuff.Length = sizeof(buff); |
abuff.Pointer = buff; |
|
status = AcpiGetIrqRoutingTable(handle, &abuff); |
if (ACPI_FAILURE(status)) { |
return AE_OK; |
} |
|
for (tbl = (ACPI_PCI_ROUTING_TABLE *)abuff.Pointer; tbl->Length; |
tbl = (ACPI_PCI_ROUTING_TABLE *) |
((char *)tbl + tbl->Length)) |
status = AcpiResourceToAddress64(acpi_res, &addr64); |
if (ACPI_SUCCESS(status)) |
{ |
ACPI_HANDLE src_handle; |
|
if (*(char*)tbl->Source == '\0') { |
add_irq(tbl->Address >> 16, tbl->Pin, tbl->SourceIndex); |
continue; |
dbgprintf(" Address range 0%x-0%x\n", |
(uint32_t)addr64.Minimum, (uint32_t)addr64.Maximum); |
} |
}; |
break; |
}; |
|
status = AcpiGetHandle(handle, tbl->Source, &src_handle); |
if (ACPI_FAILURE(status)) { |
printf("Failed AcpiGetHandle\n"); |
continue; |
} |
status = AcpiWalkResources(src_handle, METHOD_NAME__CRS, |
get_irq_resource, tbl); |
if (ACPI_FAILURE(status)) { |
printf("Failed IRQ resource\n"); |
continue; |
} |
} |
|
return AE_OK; |
} |
}; |
|
static ACPI_STATUS add_pci_root_dev(ACPI_HANDLE handle, |
UINT32 level, |
void *context, |
void **retval) |
|
static void print_dm_list() |
{ |
int i; |
static unsigned called; |
struct pci_dev *pcidev; |
struct acpi_device *acpidev; |
dmdev_t *dmdev; |
uint32_t i; |
|
if (++called > 1) { |
dbgprintf("ACPI: Warning! Multi rooted PCI is not supported!\n"); |
return AE_OK; |
} |
dbgprintf("\nDevices:\n"); |
|
for (i = 0; i < IRQ_TABLE_ENTRIES; i++) |
irqtable[i] = -1; |
|
return get_pci_irq_routing(handle); |
} |
|
static ACPI_STATUS add_pci_dev(ACPI_HANDLE handle, |
UINT32 level, |
void *context, |
void **retval) |
list_for_each_entry(dmdev, &dmdev_tree, list) |
{ |
/* skip pci root when we get to it again */ |
if (handle == pci_root_handle) |
return AE_OK; |
switch(dmdev->type) |
{ |
case 0: |
if(dmdev->acpi_dev != NULL) |
{ |
acpidev = dmdev->acpi_dev; |
dbgprintf("\n%s\n", acpidev->pnp.bus_id); |
AcpiWalkResources(acpidev->handle, METHOD_NAME__CRS, |
print_acpi_resource, NULL); |
}; |
break; |
|
return get_pci_irq_routing(handle); |
} |
|
static void scan_devices(void) |
case 1: |
if(dmdev->pci_dev != NULL) |
{ |
ACPI_STATUS status; |
pcidev = dmdev->pci_dev; |
dbgprintf("\nPCI_%x_%x bus:%d devfn: %x\n", |
pcidev->vendor, pcidev->device, |
pcidev->busnr, pcidev->devfn); |
|
/* get the root first */ |
status = AcpiGetDevices("PNP0A03", add_pci_root_dev, NULL, NULL); |
if (status != AE_OK) { |
dbgprintf("scan_devices failed (%s)\n", |
AcpiFormatException(status)); |
return; |
} |
for(i = 0; i < DEVICE_COUNT_RESOURCE; i++) |
print_pci_resource(&pcidev->resource[i]); |
|
// assert(ACPI_SUCCESS(status)); |
if(pcidev->pin) |
dbgprintf(" APIC IRQ: %d\n", acpi_get_irq(pcidev)); |
}; |
break; |
}; |
}; |
}; |
|
/* get the rest of the devices that implement _PRT */ |
status = AcpiGetDevices(NULL, add_pci_dev, NULL, NULL); |
// assert(ACPI_SUCCESS(status)); |
} |
|
#endif |
|
char* strdup(const char *str) |
{ |
size_t len = strlen (str) + 1; |
char *copy = malloc(len); |
if (copy) |
{ |
memcpy (copy, str, len); |
} |
return copy; |
} |
|