Rescue acpi irq stuff from my defect laptop. Code is disabled and should't to any harm.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36059 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -32,6 +32,7 @@ KernelMergeObject kernel_arch_x86.o :
|
|||||||
apm.cpp
|
apm.cpp
|
||||||
bios.cpp
|
bios.cpp
|
||||||
cpuid.S
|
cpuid.S
|
||||||
|
irq_routing_table.cpp
|
||||||
syscall.S
|
syscall.S
|
||||||
vm86.cpp
|
vm86.cpp
|
||||||
x86_physical_page_mapper.cpp
|
x86_physical_page_mapper.cpp
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2010, Clemens Zeidler, [email protected].
|
||||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -29,8 +30,10 @@
|
|||||||
#include <arch/x86/vm86.h>
|
#include <arch/x86/vm86.h>
|
||||||
|
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
|
#include "irq_routing_table.h"
|
||||||
|
|
||||||
#include <ACPI.h>
|
#include <ACPI.h>
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <safemode.h>
|
#include <safemode.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -578,11 +581,25 @@ ioapic_init(kernel_args *args)
|
|||||||
// TODO: remove when the PCI IRQ routing through ACPI is available below
|
// TODO: remove when the PCI IRQ routing through ACPI is available below
|
||||||
return;
|
return;
|
||||||
|
|
||||||
acpi_module_info *acpi;
|
// load acpi modul
|
||||||
if (get_module(B_ACPI_MODULE_NAME, (module_info **)&acpi) != B_OK) {
|
status_t status;
|
||||||
|
acpi_module_info* acpiModule;
|
||||||
|
status = get_module(B_ACPI_MODULE_NAME, (module_info**)&acpiModule);
|
||||||
|
if (status != B_OK) {
|
||||||
dprintf("acpi module not available, not configuring ioapic\n");
|
dprintf("acpi module not available, not configuring ioapic\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
BPrivate::CObjectDeleter<const char, status_t>
|
||||||
|
acpiModulePutter(B_ACPI_MODULE_NAME, put_module);
|
||||||
|
// load pci modul
|
||||||
|
pci_module_info* pciModule;
|
||||||
|
status = get_module(B_PCI_MODULE_NAME, (module_info**)&pciModule);
|
||||||
|
if (status != B_OK) {
|
||||||
|
dprintf("could not load pci module, not configuring ioapic\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CObjectDeleter<const char, status_t> pciModulePutter(B_PCI_MODULE_NAME,
|
||||||
|
put_module);
|
||||||
|
|
||||||
// map in the ioapic
|
// map in the ioapic
|
||||||
sIOAPIC = (ioapic *)args->arch_args.ioapic;
|
sIOAPIC = (ioapic *)args->arch_args.ioapic;
|
||||||
@@ -645,8 +662,23 @@ ioapic_init(kernel_args *args)
|
|||||||
// TODO: here ACPI needs to be used to properly set up the PCI IRQ
|
// TODO: here ACPI needs to be used to properly set up the PCI IRQ
|
||||||
// routing.
|
// routing.
|
||||||
|
|
||||||
|
IRQRoutingTable table;
|
||||||
|
status = read_irq_routing_table(pciModule, acpiModule, &table);
|
||||||
|
if (status != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// configure apic interrupts assume 1:1 mapping
|
||||||
|
for (int i = 0; i < table.Count(); i++) {
|
||||||
|
irq_routing_entry& entry = table.ElementAt(i);
|
||||||
|
irq_discriptor irqDiscriptor;
|
||||||
|
read_current_irq(acpiModule, entry.source, &irqDiscriptor);
|
||||||
|
uint32 config = 0;
|
||||||
|
config |= irqDiscriptor.polarity;
|
||||||
|
config |= irqDiscriptor.interrupt_mode;
|
||||||
|
ioapic_configure_io_interrupt(irqDiscriptor.irq, config);
|
||||||
|
}
|
||||||
|
|
||||||
// prefer the ioapic over the normal pic
|
// prefer the ioapic over the normal pic
|
||||||
put_module(B_ACPI_MODULE_NAME);
|
|
||||||
dprintf("using ioapic for interrupt routing\n");
|
dprintf("using ioapic for interrupt routing\n");
|
||||||
sCurrentPIC = &ioapicController;
|
sCurrentPIC = &ioapicController;
|
||||||
gUsingIOAPIC = true;
|
gUsingIOAPIC = true;
|
||||||
|
|||||||
@@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Clemens Zeidler [email protected]. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "irq_routing_table.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <int.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_PRT
|
||||||
|
#ifdef TRACE_PRT
|
||||||
|
# define TRACE(x...) dprintf("IRQRoutingTable: "x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
const int kIRQDescriptor = 0x04;
|
||||||
|
|
||||||
|
|
||||||
|
const char* kACPIPciRootName = "PNP0A03";
|
||||||
|
|
||||||
|
|
||||||
|
irq_discriptor::irq_discriptor()
|
||||||
|
:
|
||||||
|
irq(0),
|
||||||
|
shareable(false),
|
||||||
|
polarity(B_HIGH_ACTIVE_POLARITY),
|
||||||
|
interrupt_mode(B_EDGE_TRIGGERED)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
print_irq_discriptor(irq_discriptor* discriptor)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (discriptor->irq >> i & 0x01)
|
||||||
|
dprintf("interrupt: %i\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* activeHighString = "active high";
|
||||||
|
const char* activeLowString = " active low";
|
||||||
|
const char* levelTriggeredString = "level triggered";
|
||||||
|
const char* edgeTriggeredString = " edge triggered";
|
||||||
|
|
||||||
|
dprintf("shareable: %i, polarity: %s, interrupt_mode: %s\n",
|
||||||
|
discriptor->shareable, discriptor->polarity == B_HIGH_ACTIVE_POLARITY
|
||||||
|
? activeHighString : activeLowString,
|
||||||
|
discriptor->interrupt_mode == B_LEVEL_TRIGGERED ? levelTriggeredString
|
||||||
|
: edgeTriggeredString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
print_irq_routing_table(IRQRoutingTable* table)
|
||||||
|
{
|
||||||
|
dprintf("Print table %i entries\n", (int)table->Count());
|
||||||
|
for (int i = 0; i < table->Count(); i++) {
|
||||||
|
irq_routing_entry& entry = table->ElementAt(i);
|
||||||
|
dprintf("address: %x\n", entry.device_address);
|
||||||
|
dprintf("pin: %i\n", entry.pin);
|
||||||
|
dprintf("source: %x\n", int(entry.source));
|
||||||
|
dprintf("source index: %i\n", entry.source_index);
|
||||||
|
|
||||||
|
dprintf("pci_bus: %i\n", entry.pci_bus);
|
||||||
|
dprintf("pci_device: %i\n", entry.pci_device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
find_pci_device(pci_module_info *pci, irq_routing_entry* entry)
|
||||||
|
{
|
||||||
|
pci_info info;
|
||||||
|
int pciN = 0;
|
||||||
|
while ((*pci->get_nth_pci_info)(pciN, &info) == B_OK) {
|
||||||
|
pciN ++;
|
||||||
|
|
||||||
|
int16 deviceAddress = entry->device_address >> 16 & 0xFFFF;
|
||||||
|
if (info.device == deviceAddress
|
||||||
|
&& info.u.h0.interrupt_pin == entry->pin + 1) {
|
||||||
|
entry->pci_bus = info.bus;
|
||||||
|
entry->pci_device = info.device;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
read_device_irq_routing_table(pci_module_info *pci, acpi_module_info* acpi,
|
||||||
|
acpi_handle device, IRQRoutingTable* table)
|
||||||
|
{
|
||||||
|
acpi_data buffer;
|
||||||
|
buffer.pointer = 0;
|
||||||
|
buffer.length = ACPI_ALLOCATE_BUFFER;
|
||||||
|
status_t status = acpi->get_irq_routing_table(device, &buffer);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
acpi_object_type* object = (acpi_object_type*)buffer.pointer;
|
||||||
|
if (object->object_type != ACPI_TYPE_PACKAGE) {
|
||||||
|
free(buffer.pointer);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_routing_entry irqEntry;
|
||||||
|
acpi_pci_routing_table* acpiTable
|
||||||
|
= (acpi_pci_routing_table*)buffer.pointer;
|
||||||
|
while (acpiTable->length) {
|
||||||
|
irqEntry.device_address = acpiTable->address;
|
||||||
|
irqEntry.pin = acpiTable->pin;
|
||||||
|
irqEntry.source = acpiTable->source;
|
||||||
|
irqEntry.source_index = acpiTable->sourceIndex;
|
||||||
|
|
||||||
|
// connect to pci device
|
||||||
|
if (find_pci_device(pci, &irqEntry) != B_OK) {
|
||||||
|
TRACE("no pci dev found, device %x, pin %i\n",
|
||||||
|
irqEntry.device_address, irqEntry.pin);
|
||||||
|
acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable
|
||||||
|
+ acpiTable->length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
table->PushBack(irqEntry);
|
||||||
|
acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable
|
||||||
|
+ acpiTable->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer.pointer);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
read_irq_routing_table(pci_module_info *pci, acpi_module_info* acpi,
|
||||||
|
IRQRoutingTable* table)
|
||||||
|
{
|
||||||
|
char rootPciName[255];
|
||||||
|
acpi_handle rootPciHandle;
|
||||||
|
rootPciName[0] = 0;
|
||||||
|
status_t status = acpi->get_device(kACPIPciRootName, 0, rootPciName, 255);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = acpi->get_handle(NULL, rootPciName, &rootPciHandle);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
TRACE("Read root pci bus irq rooting table\n");
|
||||||
|
status = read_device_irq_routing_table(pci, acpi, rootPciHandle, table);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
TRACE("find p2p \n");
|
||||||
|
|
||||||
|
char result[255];
|
||||||
|
result[0] = 0;
|
||||||
|
void *counter = NULL;
|
||||||
|
while (acpi->get_next_entry(ACPI_TYPE_DEVICE, rootPciName, result, 255,
|
||||||
|
&counter) == B_OK) {
|
||||||
|
acpi_handle brigde;
|
||||||
|
status = acpi->get_handle(NULL, result, &brigde);
|
||||||
|
if (status != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = read_device_irq_routing_table(pci, acpi, brigde, table);
|
||||||
|
if (status == B_OK)
|
||||||
|
TRACE("p2p found %s\n", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
read_irq_discriptor(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
const char* method, irq_discriptor* discriptor)
|
||||||
|
{
|
||||||
|
acpi_data buffer;
|
||||||
|
buffer.pointer = NULL;
|
||||||
|
buffer.length = ACPI_ALLOCATE_BUFFER;
|
||||||
|
status_t status = acpi->evaluate_method(device, method, NULL,
|
||||||
|
&buffer);
|
||||||
|
if (status != B_OK) {
|
||||||
|
free(buffer.pointer);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_object_type* resourceBuffer = (acpi_object_type*)buffer.pointer;
|
||||||
|
if (resourceBuffer[0].object_type != ACPI_TYPE_BUFFER)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int8* resourcePointer = (int8*)resourceBuffer[0].data.buffer.buffer;
|
||||||
|
int8 integer = resourcePointer[0];
|
||||||
|
if (integer >> 3 != kIRQDescriptor) {
|
||||||
|
TRACE("resource is not a irq discriptor\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8 size = resourcePointer[0] & 0x07;
|
||||||
|
if (size < 2) {
|
||||||
|
TRACE("invalid resource size\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
discriptor->irq = resourcePointer[2];
|
||||||
|
discriptor->irq = discriptor->irq << 8;
|
||||||
|
discriptor->irq |= resourcePointer[1];
|
||||||
|
|
||||||
|
// if size equal 2 we are don't else read the third entry
|
||||||
|
if (size == 2)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
int irqInfo = resourcePointer[3];
|
||||||
|
int bit;
|
||||||
|
|
||||||
|
bit = irqInfo & 0x01;
|
||||||
|
discriptor->interrupt_mode = (bit == 0) ? B_LEVEL_TRIGGERED
|
||||||
|
: B_EDGE_TRIGGERED;
|
||||||
|
bit = irqInfo >> 3 & 0x01;
|
||||||
|
discriptor->polarity = (bit == 0) ? B_HIGH_ACTIVE_POLARITY
|
||||||
|
: B_LOW_ACTIVE_POLARITY;
|
||||||
|
discriptor->shareable = irqInfo >> 4 & 0x01;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
read_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
irq_discriptor* discriptor)
|
||||||
|
{
|
||||||
|
return read_irq_discriptor(acpi, device, "_CRS", discriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
read_possible_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
irq_discriptor* discriptor)
|
||||||
|
{
|
||||||
|
return read_irq_discriptor(acpi, device, "_PRS", discriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
set_acpi_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
irq_discriptor* discriptor)
|
||||||
|
{
|
||||||
|
acpi_object_type outBuffer;
|
||||||
|
outBuffer.object_type = ACPI_TYPE_BUFFER;
|
||||||
|
|
||||||
|
int8 data[4];
|
||||||
|
data[0] = 0x23;
|
||||||
|
data[1] = discriptor->irq & 0xFF;
|
||||||
|
data[2] = discriptor->irq >> 8;
|
||||||
|
|
||||||
|
data[3] = 0;
|
||||||
|
int8 bit;
|
||||||
|
bit = (discriptor->interrupt_mode == B_HIGH_ACTIVE_POLARITY) ? 0 : 1;
|
||||||
|
data[3] |= bit;
|
||||||
|
bit = (discriptor->polarity == B_LEVEL_TRIGGERED) ? 0 : 1;
|
||||||
|
data[3] |= bit << 3;
|
||||||
|
bit = discriptor->shareable ? 1 : 0;
|
||||||
|
data[3] |= bit << 4;
|
||||||
|
|
||||||
|
outBuffer.data.buffer.length = sizeof(data);
|
||||||
|
outBuffer.data.buffer.buffer = data;
|
||||||
|
|
||||||
|
acpi_objects parameter;
|
||||||
|
parameter.count = 1;
|
||||||
|
parameter.pointer = &outBuffer;
|
||||||
|
status_t status = acpi->evaluate_method(device, "_SRS", ¶meter, NULL);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#ifndef IRQ_ROUTING_TABLE_H
|
||||||
|
#define IRQ_ROUTING_TABLE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ACPI.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "util/Vector.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct irq_routing_entry
|
||||||
|
{
|
||||||
|
int device_address;
|
||||||
|
int8 pin;
|
||||||
|
|
||||||
|
acpi_handle source;
|
||||||
|
int source_index;
|
||||||
|
|
||||||
|
// pci busmanager connection
|
||||||
|
uchar pci_bus;
|
||||||
|
uchar pci_device;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef Vector<irq_routing_entry> IRQRoutingTable;
|
||||||
|
|
||||||
|
|
||||||
|
struct irq_discriptor
|
||||||
|
{
|
||||||
|
irq_discriptor();
|
||||||
|
// bit 0 is interrupt 0, bit 2 is interrupt 2, and so on
|
||||||
|
int16 irq;
|
||||||
|
bool shareable;
|
||||||
|
// B_LOW_ACTIVE_POLARITY or B_HIGH_ACTIVE_POLARITY
|
||||||
|
int8 polarity;
|
||||||
|
// B_LEVEL_TRIGGERED or B_EDGE_TRIGGERED
|
||||||
|
int8 interrupt_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void print_irq_discriptor(irq_discriptor* discriptor);
|
||||||
|
void print_irq_routing_table(IRQRoutingTable* table);
|
||||||
|
|
||||||
|
|
||||||
|
status_t read_irq_routing_table(pci_module_info *pci, acpi_module_info* acpi,
|
||||||
|
IRQRoutingTable* table);
|
||||||
|
status_t read_irq_discriptor(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
const char* method, irq_discriptor* discriptor);
|
||||||
|
|
||||||
|
status_t read_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
irq_discriptor* discriptor);
|
||||||
|
status_t read_possible_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
irq_discriptor* discriptor);
|
||||||
|
|
||||||
|
status_t set_acpi_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
|
irq_discriptor* discriptor);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user