Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1866 → Rev 1867

/drivers/devman/acpi.c
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;
}