[haiku-commits] Re: r36059 - haiku/trunk/src/system/kernel/arch/x86

  • From: "Clemens Zeidler" <clemens.zeidler@xxxxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 07 Apr 2010 20:30:18 +0300

Sorry for the short commit message, but my laptop refuse to work longer
then a few minutes. I got the patch, more or less, ready before my machine
broke down last week, so I risk to commit it without a final review.

Basically the patch contains a one to one mapping of the ACPI irq routing
table to the APIC pins. Also the APIC is configured using the information from ACPI.
Hope I got my new laptop before Begeistert, where I can test
it.

I think there is also still a problem with the DPC module when loading
ACPI at this early state...

        Clemens

Am 07.04.2010, 15:50 Uhr, schrieb <clemens.zeidler@xxxxxxxxxxxxxx>:

Author: czeidler
Date: 2010-04-07 14:50:55 +0200 (Wed, 07 Apr 2010)
New Revision: 36059
Changeset: http://dev.haiku-os.org/changeset/36059/haiku

Added:
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h
Modified:
   haiku/trunk/src/system/kernel/arch/x86/Jamfile
   haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp
Log:
Rescue acpi irq stuff from my defect laptop. Code is disabled and should't to any harm.

Modified: haiku/trunk/src/system/kernel/arch/x86/Jamfile
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/Jamfile 2010-04-07 07:05:20 UTC (rev 36058) +++ haiku/trunk/src/system/kernel/arch/x86/Jamfile 2010-04-07 12:50:55 UTC (rev 36059)
@@ -32,6 +32,7 @@
        apm.cpp
        bios.cpp
        cpuid.S
+       irq_routing_table.cpp
        syscall.S
        vm86.cpp
        x86_physical_page_mapper.cpp

Modified: haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2010-04-07 07:05:20 UTC (rev 36058) +++ haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2010-04-07 12:50:55 UTC (rev 36059)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2010, Clemens Zeidler, haiku@xxxxxxxxxxxxxxxxxxx
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx
  * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
  * Distributed under the terms of the MIT License.
@@ -29,8 +30,10 @@
 #include <arch/x86/vm86.h>
#include "interrupts.h"
+#include "irq_routing_table.h"
#include <ACPI.h>
+#include <AutoDeleter.h>
 #include <safemode.h>
 #include <string.h>
 #include <stdio.h>
@@ -578,11 +581,25 @@
// TODO: remove when the PCI IRQ routing through ACPI is available below
        return;
-       acpi_module_info *acpi;
-       if (get_module(B_ACPI_MODULE_NAME, (module_info **)&acpi) != B_OK) {
+       // load acpi modul
+       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");
                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
        sIOAPIC = (ioapic *)args->arch_args.ioapic;
@@ -645,8 +662,23 @@
        // TODO: here ACPI needs to be used to properly set up the PCI IRQ
        // 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
-       put_module(B_ACPI_MODULE_NAME);
        dprintf("using ioapic for interrupt routing\n");
        sCurrentPIC = &ioapicController;
        gUsingIOAPIC = true;

Added: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp (rev 0) +++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp 2010-04-07 12:50:55 UTC (rev 36059)
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2009, Clemens Zeidler haiku@xxxxxxxxxxxxxxxxxxx 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", &parameter, NULL);
+
+       return status;
+}

Added: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h (rev 0) +++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h 2010-04-07 12:50:55 UTC (rev 36059)
@@ -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




--
Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/

Other related posts: