pci/x86: Reimplement PCIe configuration mechanism using ECAM.
This allows us to drop the PCI-specific ACPI management entirely. Confirmed working on x86, and the fallbacks when there is no ACPI also still work. Change-Id: I6dac9f5539f99b934b17b341634ce22628bc66fd Reviewed-on: https://review.haiku-os.org/c/haiku/+/6470 Reviewed-by: X512 <danger_mail@list.ru> Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
19ae638fb6
commit
1a88b571ca
@ -120,6 +120,7 @@ ECAMPCIController::RegisterDevice(device_node* parent)
|
||||
}
|
||||
|
||||
|
||||
#if !defined(ECAM_PCI_CONTROLLER_NO_INIT)
|
||||
status_t
|
||||
ECAMPCIController::InitDriver(device_node* node, ECAMPCIController*& outDriver)
|
||||
{
|
||||
@ -155,6 +156,7 @@ ECAMPCIController::UninitDriver()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
addr_t
|
||||
|
@ -140,8 +140,14 @@ public:
|
||||
|
||||
protected:
|
||||
status_t ReadResourceInfo() final;
|
||||
status_t ReadResourceInfo(device_node* parent);
|
||||
|
||||
uint8 fStartBusNumber{};
|
||||
uint8 fEndBusNumber{};
|
||||
|
||||
private:
|
||||
friend class X86PCIControllerMethPcie;
|
||||
|
||||
static acpi_status AcpiCrsScanCallback(acpi_resource *res, void *context);
|
||||
inline acpi_status AcpiCrsScanCallbackInt(acpi_resource *res);
|
||||
};
|
||||
|
@ -18,7 +18,13 @@ status_t
|
||||
ECAMPCIControllerACPI::ReadResourceInfo()
|
||||
{
|
||||
DeviceNodePutter<&gDeviceManager> parent(gDeviceManager->get_parent_node(fNode));
|
||||
return ReadResourceInfo(parent.Get());
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ECAMPCIControllerACPI::ReadResourceInfo(device_node* parent)
|
||||
{
|
||||
dprintf("initialize PCI controller from ACPI\n");
|
||||
|
||||
acpi_module_info* acpiModule;
|
||||
@ -30,7 +36,7 @@ ECAMPCIControllerACPI::ReadResourceInfo()
|
||||
acpi_mcfg *mcfg;
|
||||
CHECK_RET(acpiModule->get_table(ACPI_MCFG_SIGNATURE, 0, (void**)&mcfg));
|
||||
|
||||
CHECK_RET(gDeviceManager->get_driver(parent.Get(), (driver_module_info**)&acpiDeviceModule,
|
||||
CHECK_RET(gDeviceManager->get_driver(parent, (driver_module_info**)&acpiDeviceModule,
|
||||
(void**)&acpiDevice));
|
||||
|
||||
acpi_status acpi_res = acpiDeviceModule->walk_resources(acpiDevice, (char *)"_CRS",
|
||||
@ -54,10 +60,10 @@ ECAMPCIControllerACPI::ReadResourceInfo()
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8 startBusNumber = alloc->start_bus_number;
|
||||
uint8 endBusNumber = alloc->end_bus_number;
|
||||
fStartBusNumber = alloc->start_bus_number;
|
||||
fEndBusNumber = alloc->end_bus_number;
|
||||
|
||||
fRegsLen = (endBusNumber - startBusNumber + 1) << 20;
|
||||
fRegsLen = (fEndBusNumber - fStartBusNumber + 1) << 20;
|
||||
fRegsArea.SetTo(map_physical_memory("PCI Config MMIO",
|
||||
alloc->address, fRegsLen, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&fRegs));
|
||||
|
@ -1,15 +1,17 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel busses pci x86 ;
|
||||
|
||||
SubDirC++Flags -fno-rtti ;
|
||||
SubDirC++Flags -fno-rtti -DECAM_PCI_CONTROLLER_NO_INIT ;
|
||||
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers acpi acpica include ;
|
||||
SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers acpi acpica include
|
||||
platform ;
|
||||
SubDirHdrs $(HAIKU_TOP) src system kernel arch generic ;
|
||||
|
||||
KernelAddon <pci>x86 :
|
||||
pci_acpi.cpp
|
||||
X86PCIController.cpp
|
||||
ECAMPCIController.cpp
|
||||
ECAMPCIControllerACPI.cpp
|
||||
|
||||
kernel_interface.cpp
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles ECAMPCIController.cpp ECAMPCIControllerACPI.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src add-ons kernel busses pci ecam ] ;
|
||||
|
@ -5,11 +5,9 @@
|
||||
|
||||
|
||||
#include "X86PCIController.h"
|
||||
#include "pci_acpi.h"
|
||||
|
||||
#include <AutoDeleterDrivers.h>
|
||||
#include <util/AutoLock.h>
|
||||
#include "acpi.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <new>
|
||||
@ -240,6 +238,13 @@ status_t X86PCIControllerMeth1::GetMaxBusDevices(int32& count)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
X86PCIControllerMeth1::Finalize()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
//#pragma mark - X86PCIControllerMeth2
|
||||
|
||||
|
||||
@ -327,46 +332,39 @@ status_t X86PCIControllerMeth2::GetMaxBusDevices(int32& count)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
X86PCIControllerMeth2::Finalize()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
//#pragma mark - X86PCIControllerMethPcie
|
||||
|
||||
|
||||
#define PCIE_VADDR(base, bus, slot, func, reg) ((base) + \
|
||||
((((bus) & 0xff) << 20) | (((slot) & 0x1f) << 15) | \
|
||||
(((func) & 0x7) << 12) | ((reg) & 0xfff)))
|
||||
|
||||
|
||||
status_t
|
||||
X86PCIControllerMethPcie::InitDriverInt(device_node* node)
|
||||
{
|
||||
CHECK_RET(X86PCIController::InitDriverInt(node));
|
||||
status_t status = X86PCIController::InitDriverInt(node);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
acpi_init();
|
||||
struct acpi_table_mcfg* mcfg =
|
||||
(struct acpi_table_mcfg*)acpi_find_table("MCFG");
|
||||
if (mcfg != NULL) {
|
||||
struct acpi_mcfg_allocation* end = (struct acpi_mcfg_allocation*)
|
||||
((char*)mcfg + mcfg->Header.Length);
|
||||
struct acpi_mcfg_allocation* alloc = (struct acpi_mcfg_allocation*)
|
||||
(mcfg + 1);
|
||||
for (; alloc < end; alloc++) {
|
||||
dprintf("PCI: mechanism addr: %" B_PRIx64 ", seg: %x, start: "
|
||||
"%x, end: %x\n", alloc->Address, alloc->PciSegment,
|
||||
alloc->StartBusNumber, alloc->EndBusNumber);
|
||||
if (alloc->PciSegment == 0) {
|
||||
area_id mcfgArea = map_physical_memory("acpi mcfg",
|
||||
alloc->Address, (alloc->EndBusNumber + 1) << 20,
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA
|
||||
| B_KERNEL_WRITE_AREA, (void **)&fPCIeBase);
|
||||
if (mcfgArea < 0)
|
||||
break;
|
||||
fStartBusNumber = alloc->StartBusNumber;
|
||||
fEndBusNumber = alloc->EndBusNumber;
|
||||
dprintf("PCI: mechanism pcie controller found\n");
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
// search ACPI
|
||||
device_node *acpiNode = NULL;
|
||||
{
|
||||
device_node* deviceRoot = gDeviceManager->get_root_node();
|
||||
device_attr acpiAttrs[] = {
|
||||
{ B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }},
|
||||
{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { .string = "PNP0A08" }},
|
||||
{ NULL }
|
||||
};
|
||||
if (gDeviceManager->find_child_node(deviceRoot, acpiAttrs, &acpiNode) != B_OK)
|
||||
return ENODEV;
|
||||
}
|
||||
return B_ERROR;
|
||||
|
||||
status = fECAMPCIController.ReadResourceInfo(acpiNode);
|
||||
gDeviceManager->put_node(acpiNode);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -376,27 +374,12 @@ X86PCIControllerMethPcie::ReadConfig(
|
||||
uint16 offset, uint8 size, uint32 &value)
|
||||
{
|
||||
// fallback to mechanism 1 for out of range busses
|
||||
if (bus < fStartBusNumber || bus > fEndBusNumber) {
|
||||
if (bus < fECAMPCIController.fStartBusNumber || bus > fECAMPCIController.fEndBusNumber) {
|
||||
return X86PCIControllerMeth1::ReadConfig(bus, device, function, offset,
|
||||
size, value);
|
||||
}
|
||||
|
||||
addr_t address = PCIE_VADDR(fPCIeBase, bus, device, function, offset);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
value = *(uint8*)address;
|
||||
break;
|
||||
case 2:
|
||||
value = *(uint16*)address;
|
||||
break;
|
||||
case 4:
|
||||
value = *(uint32*)address;
|
||||
break;
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
return B_OK;
|
||||
return fECAMPCIController.ReadConfig(bus, device, function, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
@ -406,32 +389,32 @@ X86PCIControllerMethPcie::WriteConfig(
|
||||
uint16 offset, uint8 size, uint32 value)
|
||||
{
|
||||
// fallback to mechanism 1 for out of range busses
|
||||
if (bus < fStartBusNumber || bus > fEndBusNumber) {
|
||||
if (bus < fECAMPCIController.fStartBusNumber || bus > fECAMPCIController.fEndBusNumber) {
|
||||
return X86PCIControllerMeth1::WriteConfig(bus, device, function, offset,
|
||||
size, value);
|
||||
}
|
||||
|
||||
addr_t address = PCIE_VADDR(fPCIeBase, bus, device, function, offset);
|
||||
switch (size) {
|
||||
case 1:
|
||||
*(uint8*)address = value;
|
||||
break;
|
||||
case 2:
|
||||
*(uint16*)address = value;
|
||||
break;
|
||||
case 4:
|
||||
*(uint32*)address = value;
|
||||
break;
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
return fECAMPCIController.WriteConfig(bus, device, function, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
status_t X86PCIControllerMethPcie::GetMaxBusDevices(int32& count)
|
||||
status_t
|
||||
X86PCIControllerMethPcie::GetMaxBusDevices(int32& count)
|
||||
{
|
||||
count = 32;
|
||||
return fECAMPCIController.GetMaxBusDevices(count);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
X86PCIControllerMethPcie::GetRange(uint32 index, pci_resource_range* range)
|
||||
{
|
||||
return fECAMPCIController.GetRange(index, range);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
X86PCIControllerMethPcie::Finalize()
|
||||
{
|
||||
// No need to call fECAMPCIController.Finalize(): IRQ routing is handled by IOAPIC on x86.
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <AutoDeleterOS.h>
|
||||
#include <lock.h>
|
||||
|
||||
#include "../ecam/ECAMPCIController.h"
|
||||
|
||||
|
||||
#define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;}
|
||||
|
||||
@ -37,6 +39,10 @@ public:
|
||||
|
||||
virtual status_t GetMaxBusDevices(int32& count) = 0;
|
||||
|
||||
virtual status_t GetRange(uint32 index, pci_resource_range* range);
|
||||
|
||||
virtual status_t Finalize() = 0;
|
||||
|
||||
status_t ReadIrq(
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 pin, uint8& irq);
|
||||
@ -45,8 +51,6 @@ public:
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 pin, uint8 irq);
|
||||
|
||||
status_t GetRange(uint32 index, pci_resource_range* range);
|
||||
|
||||
protected:
|
||||
static status_t CreateDriver(device_node* node, X86PCIController* driver,
|
||||
X86PCIController*& driverOut);
|
||||
@ -56,10 +60,6 @@ protected:
|
||||
spinlock fLock = B_SPINLOCK_INITIALIZER;
|
||||
|
||||
device_node* fNode{};
|
||||
|
||||
addr_t fPCIeBase{};
|
||||
uint8 fStartBusNumber{};
|
||||
uint8 fEndBusNumber{};
|
||||
};
|
||||
|
||||
|
||||
@ -78,6 +78,8 @@ public:
|
||||
uint16 offset, uint8 size, uint32 value) override;
|
||||
|
||||
status_t GetMaxBusDevices(int32& count) override;
|
||||
|
||||
status_t Finalize() override;
|
||||
};
|
||||
|
||||
|
||||
@ -96,6 +98,8 @@ public:
|
||||
uint16 offset, uint8 size, uint32 value) final;
|
||||
|
||||
status_t GetMaxBusDevices(int32& count) final;
|
||||
|
||||
status_t Finalize() final;
|
||||
};
|
||||
|
||||
|
||||
@ -114,6 +118,13 @@ public:
|
||||
uint16 offset, uint8 size, uint32 value) final;
|
||||
|
||||
status_t GetMaxBusDevices(int32& count) final;
|
||||
|
||||
status_t GetRange(uint32 index, pci_resource_range* range) final;
|
||||
|
||||
status_t Finalize() final;
|
||||
|
||||
private:
|
||||
ECAMPCIControllerACPI fECAMPCIController;
|
||||
};
|
||||
|
||||
|
||||
|
@ -51,6 +51,9 @@ pci_controller_module_info gPciControllerDriver = {
|
||||
},
|
||||
.get_range = [](void *cookie, uint32 index, pci_resource_range* range) {
|
||||
return static_cast<X86PCIController*>(cookie)->GetRange(index, range);
|
||||
},
|
||||
.finalize = [](void *cookie) {
|
||||
return static_cast<X86PCIController*>(cookie)->Finalize();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,313 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
|
||||
* Copyright 2007, Michael Lotz, mmlr@mlotz.ch
|
||||
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_acpi.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <boot_item.h>
|
||||
#include <acpi.h>
|
||||
|
||||
|
||||
//#define TRACE_ACPI
|
||||
#ifdef TRACE_ACPI
|
||||
# define TRACE(x...) dprintf(x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
#define ERROR(x...) dprintf(x)
|
||||
|
||||
static struct scan_spots_struct acpi_scan_spots[] = {
|
||||
{ 0x0, 0x1000, 0x1000 },
|
||||
{ 0x9f000, 0x10000, 0x1000 },
|
||||
{ 0xe0000, 0x110000, 0x20000 },
|
||||
{ 0xfd000, 0xfe000, 0x1000},
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static acpi_descriptor_header* sAcpiRsdt; // System Description Table
|
||||
static acpi_descriptor_header* sAcpiXsdt; // Extended System Description Table
|
||||
static int32 sNumEntries = -1;
|
||||
|
||||
|
||||
static status_t
|
||||
acpi_validate_rsdp(acpi_rsdp* rsdp)
|
||||
{
|
||||
const char* data = (const char*)rsdp;
|
||||
unsigned char checksum = 0;
|
||||
for (uint32 i = 0; i < sizeof(acpi_rsdp_legacy); i++)
|
||||
checksum += data[i];
|
||||
|
||||
if ((checksum & 0xff) != 0) {
|
||||
TRACE("acpi: rsdp failed basic checksum\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
// for ACPI 2.0+ we need to also validate the extended checksum
|
||||
if (rsdp->revision > 0) {
|
||||
for (uint32 i = sizeof(acpi_rsdp_legacy);
|
||||
i < sizeof(acpi_rsdp_extended); i++) {
|
||||
checksum += data[i];
|
||||
}
|
||||
|
||||
if ((checksum & 0xff) != 0) {
|
||||
ERROR("acpi: rsdp failed extended checksum\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
acpi_validate_rsdt(acpi_descriptor_header* rsdt)
|
||||
{
|
||||
const char* data = (const char*)rsdt;
|
||||
unsigned char checksum = 0;
|
||||
for (uint32 i = 0; i < rsdt->length; i++)
|
||||
checksum += data[i];
|
||||
|
||||
return checksum == 0 ? B_OK : B_BAD_DATA;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
acpi_check_rsdt(acpi_rsdp* rsdp)
|
||||
{
|
||||
if (acpi_validate_rsdp(rsdp) != B_OK)
|
||||
return B_BAD_DATA;
|
||||
|
||||
bool usingXsdt = false;
|
||||
|
||||
TRACE("acpi: found rsdp at %p oem id: %.6s, rev %d\n",
|
||||
rsdp, rsdp->oem_id, rsdp->revision);
|
||||
TRACE("acpi: rsdp points to rsdt at 0x%" B_PRIx32 "\n", rsdp->rsdt_address);
|
||||
|
||||
uint32 length = 0;
|
||||
acpi_descriptor_header* rsdt = NULL;
|
||||
area_id rsdtArea = -1;
|
||||
if (rsdp->revision > 0) {
|
||||
length = rsdp->xsdt_length;
|
||||
rsdtArea = map_physical_memory("rsdt acpi",
|
||||
(uint32)rsdp->xsdt_address, rsdp->xsdt_length, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA, (void **)&rsdt);
|
||||
if (rsdt != NULL
|
||||
&& strncmp(rsdt->signature, ACPI_XSDT_SIGNATURE, 4) != 0) {
|
||||
delete_area(rsdtArea);
|
||||
rsdt = NULL;
|
||||
ERROR("acpi: invalid extended system description table\n");
|
||||
} else
|
||||
usingXsdt = true;
|
||||
}
|
||||
|
||||
// if we're ACPI v1 or we fail to map the XSDT for some reason,
|
||||
// attempt to use the RSDT instead.
|
||||
if (rsdt == NULL) {
|
||||
// map and validate the root system description table
|
||||
rsdtArea = map_physical_memory("rsdt acpi",
|
||||
rsdp->rsdt_address, sizeof(acpi_descriptor_header),
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&rsdt);
|
||||
if (rsdt == NULL) {
|
||||
ERROR("acpi: couldn't map rsdt header\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) {
|
||||
delete_area(rsdtArea);
|
||||
rsdt = NULL;
|
||||
ERROR("acpi: invalid root system description table\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
length = rsdt->length;
|
||||
// Map the whole table, not just the header
|
||||
TRACE("acpi: rsdt length: %" B_PRIu32 "\n", length);
|
||||
delete_area(rsdtArea);
|
||||
rsdtArea = map_physical_memory("rsdt acpi",
|
||||
rsdp->rsdt_address, length, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA, (void **)&rsdt);
|
||||
}
|
||||
|
||||
if (rsdt != NULL) {
|
||||
if (acpi_validate_rsdt(rsdt) != B_OK) {
|
||||
TRACE("acpi: rsdt failed checksum validation\n");
|
||||
delete_area(rsdtArea);
|
||||
return B_ERROR;
|
||||
} else {
|
||||
if (usingXsdt)
|
||||
sAcpiXsdt = rsdt;
|
||||
else
|
||||
sAcpiRsdt = rsdt;
|
||||
TRACE("acpi: found valid %s at %p\n",
|
||||
usingXsdt ? ACPI_XSDT_SIGNATURE : ACPI_RSDT_SIGNATURE,
|
||||
rsdt);
|
||||
}
|
||||
} else
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
template<typename PointerType>
|
||||
acpi_descriptor_header*
|
||||
acpi_find_table_generic(const char* signature, acpi_descriptor_header* acpiSdt)
|
||||
{
|
||||
if (acpiSdt == NULL)
|
||||
return NULL;
|
||||
|
||||
if (sNumEntries == -1) {
|
||||
// if using the xsdt, our entries are 64 bits wide.
|
||||
sNumEntries = (acpiSdt->length
|
||||
- sizeof(acpi_descriptor_header))
|
||||
/ sizeof(PointerType);
|
||||
}
|
||||
|
||||
if (sNumEntries <= 0) {
|
||||
ERROR("acpi: root system description table is empty\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRACE("acpi: searching %" B_PRId32 " entries for table '%.4s'\n", sNumEntries,
|
||||
signature);
|
||||
|
||||
PointerType* pointer = (PointerType*)((uint8*)acpiSdt
|
||||
+ sizeof(acpi_descriptor_header));
|
||||
|
||||
acpi_descriptor_header* header = NULL;
|
||||
area_id headerArea = -1;
|
||||
for (int32 j = 0; j < sNumEntries; j++, pointer++) {
|
||||
headerArea = map_physical_memory("acpi header", (uint32)*pointer,
|
||||
sizeof(acpi_descriptor_header), B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA, (void **)&header);
|
||||
|
||||
if (header == NULL
|
||||
|| strncmp(header->signature, signature, 4) != 0) {
|
||||
// not interesting for us
|
||||
TRACE("acpi: Looking for '%.4s'. Skipping '%.4s'\n",
|
||||
signature, header != NULL ? header->signature : "null");
|
||||
|
||||
if (header != NULL) {
|
||||
delete_area(headerArea);
|
||||
header = NULL;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
TRACE("acpi: Found '%.4s' @ %p\n", signature, pointer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (header == NULL)
|
||||
return NULL;
|
||||
|
||||
// Map the whole table, not just the header
|
||||
uint32 length = header->length;
|
||||
delete_area(headerArea);
|
||||
|
||||
headerArea = map_physical_memory("acpi table",
|
||||
(uint32)*pointer, length, B_ANY_KERNEL_ADDRESS,
|
||||
B_KERNEL_READ_AREA, (void **)&header);
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
acpi_find_table(const char* signature)
|
||||
{
|
||||
if (sAcpiRsdt != NULL)
|
||||
return acpi_find_table_generic<uint32>(signature, sAcpiRsdt);
|
||||
else if (sAcpiXsdt != NULL)
|
||||
return acpi_find_table_generic<uint64>(signature, sAcpiXsdt);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
acpi_init()
|
||||
{
|
||||
// Try pointer from boot loader, if any
|
||||
phys_addr_t* acpiRootPointer = (phys_addr_t*)get_boot_item("ACPI_ROOT_POINTER", NULL);
|
||||
if (acpiRootPointer != NULL) {
|
||||
acpi_rsdp* rsdp = NULL;
|
||||
area_id rsdpArea = map_physical_memory("acpi rsdp",
|
||||
*acpiRootPointer, B_PAGE_SIZE,
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&rsdp);
|
||||
if (rsdpArea < B_OK) {
|
||||
ERROR("acpi_init: couldn't map %s\n", strerror(rsdpArea));
|
||||
} else {
|
||||
status_t status = B_ERROR;
|
||||
if (strncmp((char*)rsdp, ACPI_RSDP_SIGNATURE, 8) == 0)
|
||||
status = acpi_check_rsdt(rsdp);
|
||||
delete_area(rsdpArea);
|
||||
if (status == B_OK)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find the ACPI RSDP in EBDA
|
||||
uint8* start = NULL;
|
||||
area_id ebdaArea = map_physical_memory("ebda", 0, B_PAGE_SIZE,
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&start);
|
||||
if (ebdaArea < 0) {
|
||||
ERROR("acpi_init: couldn't map 1K: %s\n", strerror(ebdaArea));
|
||||
} else {
|
||||
phys_addr_t ebda = *(uint16*)&start[0x40e];
|
||||
ebda <<= 4;
|
||||
TRACE("acpi_init: 0x%lx\n", ebda);
|
||||
delete_area(ebdaArea);
|
||||
if (ebda > 0x400) {
|
||||
acpi_scan_spots[0].start = ebda;
|
||||
acpi_scan_spots[0].stop = ebda + 0x1000;
|
||||
acpi_scan_spots[0].length = 0x1000;
|
||||
// will be scanned first
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find the ACPI RSDP.
|
||||
for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) {
|
||||
acpi_rsdp* rsdp = NULL;
|
||||
|
||||
TRACE("acpi_init: entry base 0x%" B_PRIx32 ", limit 0x%" B_PRIx32 "\n",
|
||||
acpi_scan_spots[i].start, acpi_scan_spots[i].stop);
|
||||
|
||||
char* start = NULL;
|
||||
area_id rsdpArea = map_physical_memory("acpi rsdp",
|
||||
acpi_scan_spots[i].start, acpi_scan_spots[i].length,
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&start);
|
||||
if (rsdpArea < B_OK) {
|
||||
ERROR("acpi_init: couldn't map %s\n", strerror(rsdpArea));
|
||||
break;
|
||||
}
|
||||
for (char *pointer = start;
|
||||
(addr_t)pointer < (addr_t)start + acpi_scan_spots[i].length;
|
||||
pointer += 16) {
|
||||
if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) {
|
||||
TRACE("acpi_init: found ACPI RSDP signature at %p\n",
|
||||
pointer);
|
||||
rsdp = (acpi_rsdp*)pointer;
|
||||
}
|
||||
}
|
||||
|
||||
if (rsdp != NULL && acpi_check_rsdt(rsdp) == B_OK) {
|
||||
delete_area(rsdpArea);
|
||||
break;
|
||||
}
|
||||
delete_area(rsdpArea);
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PCI_ACPI_H
|
||||
#define PCI_ACPI_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct scan_spots_struct {
|
||||
uint32 start;
|
||||
uint32 stop;
|
||||
uint32 length;
|
||||
};
|
||||
|
||||
void *acpi_find_table(const char *signature);
|
||||
void acpi_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PCI_ACPI_H */
|
Loading…
x
Reference in New Issue
Block a user