pci: generic MSI interrupts support
Change-Id: Ib4fd23f6bca867a2b428bf2651234d719ee08672 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6221 Reviewed-by: waddlesplash <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
@@ -38,6 +38,23 @@ typedef struct pci_device_module_info {
|
|||||||
uint16 *offset);
|
uint16 *offset);
|
||||||
uint8 (*get_powerstate)(pci_device *device);
|
uint8 (*get_powerstate)(pci_device *device);
|
||||||
void (*set_powerstate)(pci_device *device, uint8 state);
|
void (*set_powerstate)(pci_device *device, uint8 state);
|
||||||
|
|
||||||
|
// MSI/MSI-X
|
||||||
|
uint8 (*get_msi_count)(pci_device *device);
|
||||||
|
status_t (*configure_msi)(pci_device *device,
|
||||||
|
uint8 count,
|
||||||
|
uint8 *startVector);
|
||||||
|
status_t (*unconfigure_msi)(pci_device *device);
|
||||||
|
|
||||||
|
status_t (*enable_msi)(pci_device *device);
|
||||||
|
status_t (*disable_msi)(pci_device *device);
|
||||||
|
|
||||||
|
uint8 (*get_msix_count)(pci_device *device);
|
||||||
|
status_t (*configure_msix)(pci_device *device,
|
||||||
|
uint8 count,
|
||||||
|
uint8 *startVector);
|
||||||
|
status_t (*enable_msix)(pci_device *device);
|
||||||
|
|
||||||
} pci_device_module_info;
|
} pci_device_module_info;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022, Haiku Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_GENERIC_MSI_H
|
||||||
|
#define _KERNEL_ARCH_GENERIC_MSI_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
class MSIInterface {
|
||||||
|
public:
|
||||||
|
virtual status_t AllocateVectors(
|
||||||
|
uint8 count, uint8& startVector, uint64& address, uint16& data) = 0;
|
||||||
|
virtual void FreeVectors(uint8 count, uint8 startVector) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void msi_set_interface(MSIInterface* interface);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool msi_supported();
|
||||||
|
status_t msi_allocate_vectors(uint8 count, uint8 *startVector,
|
||||||
|
uint64 *address, uint16 *data);
|
||||||
|
void msi_free_vectors(uint8 count, uint8 startVector);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KERNEL_ARCH_GENERIC_MSI_H
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef _KERNEL_ARCH_x86_MSI_H
|
#ifndef _KERNEL_ARCH_x86_MSI_H
|
||||||
#define _KERNEL_ARCH_x86_MSI_H
|
#define _KERNEL_ARCH_x86_MSI_H
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <arch/generic/msi.h>
|
||||||
|
|
||||||
// address register
|
// address register
|
||||||
#define MSI_ADDRESS_BASE 0xfee00000
|
#define MSI_ADDRESS_BASE 0xfee00000
|
||||||
@@ -24,10 +24,7 @@
|
|||||||
#define MSI_DELIVERY_MODE_EXT_INT 0x00000700
|
#define MSI_DELIVERY_MODE_EXT_INT 0x00000700
|
||||||
|
|
||||||
|
|
||||||
bool msi_supported();
|
|
||||||
status_t msi_allocate_vectors(uint8 count, uint8 *startVector,
|
|
||||||
uint64 *address, uint16 *data);
|
|
||||||
void msi_free_vectors(uint8 count, uint8 startVector);
|
|
||||||
void msi_assign_interrupt_to_cpu(uint8 irq, int32 cpu);
|
void msi_assign_interrupt_to_cpu(uint8 irq, int32 cpu);
|
||||||
|
|
||||||
|
|
||||||
#endif // _KERNEL_ARCH_x86_MSI_H
|
#endif // _KERNEL_ARCH_x86_MSI_H
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ KernelAddon pci :
|
|||||||
pci_module.cpp
|
pci_module.cpp
|
||||||
pci_root.cpp
|
pci_root.cpp
|
||||||
pci_device.cpp
|
pci_device.cpp
|
||||||
|
pci_msi.cpp
|
||||||
: pci_arch_bus_manager.a
|
: pci_arch_bus_manager.a
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -75,20 +75,29 @@ PCIFU740::InitMSI(int32 msiIrq)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msi_set_interface(static_cast<MSIInterface*>(this));
|
||||||
|
|
||||||
dprintf(" fMsiStartIrq: %ld\n", fMsiStartIrq);
|
dprintf(" fMsiStartIrq: %ld\n", fMsiStartIrq);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
status_t
|
||||||
PCIFU740::AllocateMSIIrq()
|
PCIFU740::AllocateVectors(uint8 count, uint8& startVector, uint64& address, uint16& data)
|
||||||
{
|
{
|
||||||
|
if (count != 1)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
if (((1 << i) & fAllocatedMsiIrqs[0]) == 0) {
|
if (((1 << i) & fAllocatedMsiIrqs[0]) == 0) {
|
||||||
fAllocatedMsiIrqs[0] |= (1 << i);
|
fAllocatedMsiIrqs[0] |= (1 << i);
|
||||||
GetDbuRegs()->msiIntr[0].mask &= ~(1 << i);
|
GetDbuRegs()->msiIntr[0].mask &= ~(1 << i);
|
||||||
return i;
|
|
||||||
|
startVector = fMsiStartIrq + i;
|
||||||
|
address = fMsiPhysAddr;
|
||||||
|
data = i;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -96,12 +105,17 @@ PCIFU740::AllocateMSIIrq()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PCIFU740::FreeMSIIrq(int32 irq)
|
PCIFU740::FreeVectors(uint8 count, uint8 startVector)
|
||||||
{
|
{
|
||||||
|
int32 irq = (int32)startVector - fMsiStartIrq;
|
||||||
|
while (count > 0) {
|
||||||
if (irq >= 0 && irq < 32 && ((1 << irq) & fAllocatedMsiIrqs[0]) != 0) {
|
if (irq >= 0 && irq < 32 && ((1 << irq) & fAllocatedMsiIrqs[0]) != 0) {
|
||||||
GetDbuRegs()->msiIntr[0].mask |= (1 << (uint32)irq);
|
GetDbuRegs()->msiIntr[0].mask |= (1 << (uint32)irq);
|
||||||
fAllocatedMsiIrqs[0] &= ~(1 << (uint32)irq);
|
fAllocatedMsiIrqs[0] &= ~(1 << (uint32)irq);
|
||||||
}
|
}
|
||||||
|
irq++;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -400,68 +414,3 @@ PCIFU740::ConfigAddress(uint8 bus, uint8 device, uint8 function, uint16 offset)
|
|||||||
|
|
||||||
return fConfigBase + offset;
|
return fConfigBase + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PCIFU740::InitDeviceMSI(uint8 bus, uint8 device, uint8 function)
|
|
||||||
{
|
|
||||||
uint32 status;
|
|
||||||
uint32 capPtr;
|
|
||||||
uint32 capId;
|
|
||||||
|
|
||||||
ReadConfig(NULL, bus, device, function, PCI_status, 2, &status);
|
|
||||||
if ((status & PCI_status_capabilities) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32 headerType;
|
|
||||||
ReadConfig(NULL, bus, device, function, PCI_header_type, 1, &headerType);
|
|
||||||
|
|
||||||
switch (headerType & PCI_header_type_mask) {
|
|
||||||
case PCI_header_type_generic:
|
|
||||||
case PCI_header_type_PCI_to_PCI_bridge:
|
|
||||||
ReadConfig(NULL, bus, device, function, PCI_capabilities_ptr, 1, &capPtr);
|
|
||||||
break;
|
|
||||||
case PCI_header_type_cardbus:
|
|
||||||
ReadConfig(NULL, bus, device, function, PCI_capabilities_ptr_2, 1, &capPtr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
capPtr &= ~3;
|
|
||||||
if (capPtr == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < 48; i++) {
|
|
||||||
ReadConfig(NULL, bus, device, function, capPtr + 0, 1, &capId);
|
|
||||||
|
|
||||||
if (capId == PCI_cap_id_msi)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ReadConfig(NULL, bus, device, function, capPtr + 1, 1, &capPtr);
|
|
||||||
capPtr &= ~3;
|
|
||||||
if (capPtr == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf(" MSI offset: %#x\n", capPtr);
|
|
||||||
|
|
||||||
int32 msiIrq = AllocateMSIIrq();
|
|
||||||
dprintf(" msiIrq: %" B_PRId32 "\n", msiIrq);
|
|
||||||
|
|
||||||
uint32 control;
|
|
||||||
ReadConfig(NULL, bus, device, function, capPtr + PCI_msi_control, 2, &control);
|
|
||||||
|
|
||||||
WriteConfig(NULL, bus, device, function, capPtr + PCI_msi_address, 4, (uint32)fMsiPhysAddr);
|
|
||||||
if ((control & PCI_msi_control_64bit) != 0) {
|
|
||||||
WriteConfig(NULL, bus, device, function, capPtr + PCI_msi_address_high, 4, (uint32)(fMsiPhysAddr >> 32));
|
|
||||||
WriteConfig(NULL, bus, device, function, capPtr + PCI_msi_data_64bit, 2, msiIrq);
|
|
||||||
} else
|
|
||||||
WriteConfig(NULL, bus, device, function, capPtr + PCI_msi_data, 2, msiIrq);
|
|
||||||
|
|
||||||
control &= ~PCI_msi_control_mme_mask;
|
|
||||||
control |= (ffs(1) - 1) << 4;
|
|
||||||
control |= PCI_msi_control_enable;
|
|
||||||
WriteConfig(NULL, bus, device, function, capPtr + PCI_msi_control, 2, control);
|
|
||||||
WriteConfig(NULL, bus, device, function, PCI_interrupt_line, 1, fMsiStartIrq + msiIrq);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "arch_pci_controller.h"
|
#include "arch_pci_controller.h"
|
||||||
|
#include <arch/generic/msi.h>
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -39,22 +40,82 @@ struct PciAtuRegs {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PCIFU740 : public ArchPCIController {
|
struct PciDbiRegs {
|
||||||
|
uint8 unknown0[0x700];
|
||||||
|
|
||||||
|
uint32 unknown1[3];
|
||||||
|
uint32 portAfr;
|
||||||
|
uint32 linkControl;
|
||||||
|
uint32 unknown2[5];
|
||||||
|
uint32 portDebug0;
|
||||||
|
uint32 portDebug1;
|
||||||
|
uint32 unknown3[55];
|
||||||
|
uint32 linkWidthSpeedControl;
|
||||||
|
uint32 unknown4[4];
|
||||||
|
uint32 msiAddrLo;
|
||||||
|
uint32 msiAddrHi;
|
||||||
|
struct {
|
||||||
|
uint32 enable;
|
||||||
|
uint32 mask;
|
||||||
|
uint32 status;
|
||||||
|
} msiIntr[8];
|
||||||
|
uint32 unknown5[13];
|
||||||
|
uint32 miscControl1Off;
|
||||||
|
uint32 miscPortMultiLaneCtrl;
|
||||||
|
uint32 unknown6[15];
|
||||||
|
|
||||||
|
uint32 atuViewport;
|
||||||
|
uint32 atuCr1;
|
||||||
|
uint32 atuCr2;
|
||||||
|
uint32 atuBaseLo;
|
||||||
|
uint32 atuBaseHi;
|
||||||
|
uint32 atuLimit;
|
||||||
|
uint32 atuTargetLo;
|
||||||
|
uint32 atuTargetHi;
|
||||||
|
uint32 unknown7;
|
||||||
|
uint32 atuLimitHi;
|
||||||
|
uint32 unknown8[8];
|
||||||
|
|
||||||
|
uint32 msixDoorbell;
|
||||||
|
uint32 unknown9[117];
|
||||||
|
|
||||||
|
uint32 plChkRegControlStatus;
|
||||||
|
uint32 unknown10;
|
||||||
|
uint32 plChkRegErrAddr;
|
||||||
|
uint32 unknown11[309];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PCIFU740 : public ArchPCIController, public MSIInterface {
|
||||||
|
|
||||||
status_t Init(device_node* pciRootNode);
|
status_t Init(device_node* pciRootNode);
|
||||||
|
|
||||||
status_t InitMSI(int32 irq);
|
PciDbiRegs volatile* GetDbuRegs() {return (PciDbiRegs volatile*)fDbiBase;}
|
||||||
int32 AllocateMSIIrq();
|
|
||||||
void FreeMSIIrq(int32 irq);
|
|
||||||
int32 HandleMSIIrq(void* arg);
|
|
||||||
|
|
||||||
|
status_t InitMSI(int32 irq);
|
||||||
|
status_t AllocateVectors(uint8 count, uint8& startVector, uint64& address,
|
||||||
|
uint16& data) final;
|
||||||
|
void FreeVectors(uint8 count, uint8 startVector) final;
|
||||||
|
static int32 HandleMSIIrq(void* arg);
|
||||||
|
inline int32 HandleMSIIrqInt();
|
||||||
|
|
||||||
|
void EnableIoInterrupt(int irq) final;
|
||||||
|
void DisableIoInterrupt(int irq) final;
|
||||||
|
void ConfigureIoInterrupt(int irq, uint32 config) final;
|
||||||
|
int32 AssignToCpu(int32 irq, int32 cpu) final;
|
||||||
|
|
||||||
addr_t ConfigAddress(uint8 bus, uint8 device, uint8 function, uint16 offset);
|
addr_t ConfigAddress(uint8 bus, uint8 device, uint8 function, uint16 offset);
|
||||||
void InitDeviceMSI(uint8 bus, uint8 device, uint8 function);
|
|
||||||
bool AllocateBar() { return false; }
|
bool AllocateBar() { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t AtuMap(uint32 index, uint32 direction, uint32 type,
|
status_t AtuMap(uint32 index, uint32 direction, uint32 type,
|
||||||
uint64 parentAdr, uint64 childAdr, uint32 size);
|
uint64 parentAdr, uint64 childAdr, uint32 size);
|
||||||
void AtuDump();
|
void AtuDump();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AreaDeleter fDbiArea;
|
||||||
|
addr_t fDbiPhysBase{};
|
||||||
|
addr_t fDbiBase{};
|
||||||
|
size_t fDbiSize{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,8 @@ SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers acpi arch $(TARGET_KERNE
|
|||||||
|
|
||||||
KernelStaticLibrary pci_arch_bus_manager :
|
KernelStaticLibrary pci_arch_bus_manager :
|
||||||
pci_acpi.cpp
|
pci_acpi.cpp
|
||||||
pci_arch_info.cpp
|
|
||||||
pci_arch_module.cpp
|
|
||||||
pci_bios.cpp
|
pci_bios.cpp
|
||||||
pci_controller.cpp
|
pci_controller.cpp
|
||||||
pci_io.cpp
|
pci_io.cpp
|
||||||
pci_irq.cpp
|
pci_irq.cpp
|
||||||
pci_msi.cpp
|
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pci_arch_info.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
pci_read_arch_info(PCIDev *dev)
|
|
||||||
{
|
|
||||||
pci_read_msi_info(dev);
|
|
||||||
pci_read_msix_info(dev);
|
|
||||||
pci_read_ht_mapping_info(dev);
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef _PCI_ARCH_INFO_H
|
|
||||||
#define _PCI_ARCH_INFO_H
|
|
||||||
|
|
||||||
#include "pci_msi.h"
|
|
||||||
|
|
||||||
typedef struct pci_arch_info {
|
|
||||||
msi_info msi;
|
|
||||||
msix_info msix;
|
|
||||||
ht_mapping_info ht_mapping;
|
|
||||||
} pci_arch_info;
|
|
||||||
|
|
||||||
|
|
||||||
void pci_read_arch_info(PCIDev *device);
|
|
||||||
|
|
||||||
#endif // _PCI_ARCH_INFO_H
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <PCI.h>
|
|
||||||
#include <PCI_x86.h>
|
|
||||||
#include "pci_msi.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int32
|
|
||||||
pci_arch_module_std_ops(int32 op, ...)
|
|
||||||
{
|
|
||||||
switch (op) {
|
|
||||||
case B_MODULE_INIT:
|
|
||||||
{
|
|
||||||
module_info *dummy;
|
|
||||||
status_t result = get_module(B_PCI_MODULE_NAME, &dummy);
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_MODULE_UNINIT:
|
|
||||||
put_module(B_PCI_MODULE_NAME);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pci_x86_module_info gPCIArchModule = {
|
|
||||||
{
|
|
||||||
B_PCI_X86_MODULE_NAME,
|
|
||||||
0,
|
|
||||||
pci_arch_module_std_ops
|
|
||||||
},
|
|
||||||
|
|
||||||
&pci_get_msi_count,
|
|
||||||
&pci_configure_msi,
|
|
||||||
&pci_unconfigure_msi,
|
|
||||||
&pci_enable_msi,
|
|
||||||
&pci_disable_msi,
|
|
||||||
&pci_get_msix_count,
|
|
||||||
&pci_configure_msix,
|
|
||||||
&pci_enable_msix
|
|
||||||
};
|
|
||||||
@@ -1551,9 +1551,9 @@ PCI::_RefreshDeviceInfo(PCIBus *bus)
|
|||||||
for (PCIDev *dev = bus->child; dev; dev = dev->next) {
|
for (PCIDev *dev = bus->child; dev; dev = dev->next) {
|
||||||
_ReadBasicInfo(dev);
|
_ReadBasicInfo(dev);
|
||||||
_ReadHeaderInfo(dev);
|
_ReadHeaderInfo(dev);
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
pci_read_msi_info(dev);
|
||||||
pci_read_arch_info(dev);
|
pci_read_msix_info(dev);
|
||||||
#endif
|
pci_read_ht_mapping_info(dev);
|
||||||
if (dev->child)
|
if (dev->child)
|
||||||
_RefreshDeviceInfo(dev->child);
|
_RefreshDeviceInfo(dev->child);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pci_controller.h"
|
#include "pci_controller.h"
|
||||||
|
#include "pci_msi.h"
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
|
||||||
#include "pci_arch_info.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TRACE_PCI
|
#define TRACE_PCI
|
||||||
#ifndef TRACE_PCI
|
#ifndef TRACE_PCI
|
||||||
@@ -47,9 +45,10 @@ struct PCIDev {
|
|||||||
uint8 device;
|
uint8 device;
|
||||||
uint8 function;
|
uint8 function;
|
||||||
pci_info info;
|
pci_info info;
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
|
||||||
pci_arch_info arch_info;
|
msi_info msi;
|
||||||
#endif
|
msix_info msix;
|
||||||
|
ht_mapping_info ht_mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <PCI.h>
|
#include <PCI.h>
|
||||||
|
#include <PCI_x86.h>
|
||||||
|
#include "pci_msi.h"
|
||||||
|
|
||||||
#include "pci_private.h"
|
#include "pci_private.h"
|
||||||
#include "pci_info.h"
|
#include "pci_info.h"
|
||||||
@@ -14,7 +16,6 @@
|
|||||||
|
|
||||||
|
|
||||||
device_manager_info *gDeviceManager;
|
device_manager_info *gDeviceManager;
|
||||||
extern struct pci_arch_module gPCIArchModule;
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
pci_old_module_std_ops(int32 op, ...)
|
pci_old_module_std_ops(int32 op, ...)
|
||||||
@@ -45,6 +46,29 @@ pci_old_module_std_ops(int32 op, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32
|
||||||
|
pci_arch_module_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
{
|
||||||
|
module_info *dummy;
|
||||||
|
status_t result = get_module(B_PCI_MODULE_NAME, &dummy);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct pci_module_info sOldPCIModule = {
|
static struct pci_module_info sOldPCIModule = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -73,6 +97,25 @@ static struct pci_module_info sOldPCIModule = {
|
|||||||
&pci_set_powerstate
|
&pci_set_powerstate
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static pci_x86_module_info sPCIArchModule = {
|
||||||
|
{
|
||||||
|
B_PCI_X86_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
pci_arch_module_std_ops
|
||||||
|
},
|
||||||
|
|
||||||
|
&pci_get_msi_count,
|
||||||
|
&pci_configure_msi,
|
||||||
|
&pci_unconfigure_msi,
|
||||||
|
&pci_enable_msi,
|
||||||
|
&pci_disable_msi,
|
||||||
|
&pci_get_msix_count,
|
||||||
|
&pci_configure_msix,
|
||||||
|
&pci_enable_msix
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
{B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager},
|
{B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager},
|
||||||
{}
|
{}
|
||||||
@@ -92,9 +135,6 @@ module_info *modules[] = {
|
|||||||
(module_info *)&gPCIRootModule,
|
(module_info *)&gPCIRootModule,
|
||||||
(module_info *)&gPCIDeviceModule,
|
(module_info *)&gPCIDeviceModule,
|
||||||
(module_info *)&gPCILegacyDriverModule,
|
(module_info *)&gPCILegacyDriverModule,
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
(module_info *)&sPCIArchModule,
|
||||||
// add platforms when they provide an arch specific module
|
|
||||||
(module_info *)&gPCIArchModule,
|
|
||||||
#endif
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
+14
-15
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pci_msi.h"
|
#include "pci_msi.h"
|
||||||
#include "pci_arch_info.h"
|
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "pci_private.h"
|
#include "pci_private.h"
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ static status_t pci_disable_msix(PCIDev *device);
|
|||||||
static void
|
static void
|
||||||
pci_ht_msi_map(PCIDev *device, uint64 address)
|
pci_ht_msi_map(PCIDev *device, uint64 address)
|
||||||
{
|
{
|
||||||
ht_mapping_info *info = &device->arch_info.ht_mapping;
|
ht_mapping_info *info = &device->ht_mapping;
|
||||||
if (!info->ht_mapping_capable)
|
if (!info->ht_mapping_capable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ pci_read_ht_mapping_info(PCIDev *device)
|
|||||||
if (!msi_supported())
|
if (!msi_supported())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ht_mapping_info *info = &device->arch_info.ht_mapping;
|
ht_mapping_info *info = &device->ht_mapping;
|
||||||
info->ht_mapping_capable = false;
|
info->ht_mapping_capable = false;
|
||||||
|
|
||||||
uint8 offset = 0;
|
uint8 offset = 0;
|
||||||
@@ -90,7 +89,7 @@ pci_get_msi_count(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
msi_info *info = &device->arch_info.msi;
|
msi_info *info = &device->msi;
|
||||||
if (!info->msi_capable)
|
if (!info->msi_capable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -118,7 +117,7 @@ pci_configure_msi(uint8 virtualBus, uint8 _device, uint8 function,
|
|||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
msi_info *info = &device->arch_info.msi;
|
msi_info *info = &device->msi;
|
||||||
if (!info->msi_capable)
|
if (!info->msi_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -177,7 +176,7 @@ pci_unconfigure_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (result != B_UNSUPPORTED && result != B_NO_INIT)
|
if (result != B_UNSUPPORTED && result != B_NO_INIT)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
msi_info *info = &device->arch_info.msi;
|
msi_info *info = &device->msi;
|
||||||
if (!info->msi_capable)
|
if (!info->msi_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -213,7 +212,7 @@ pci_enable_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
msi_info *info = &device->arch_info.msi;
|
msi_info *info = &device->msi;
|
||||||
if (!info->msi_capable)
|
if (!info->msi_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -259,7 +258,7 @@ pci_disable_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (result != B_UNSUPPORTED && result != B_NO_INIT)
|
if (result != B_UNSUPPORTED && result != B_NO_INIT)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
msi_info *info = &device->arch_info.msi;
|
msi_info *info = &device->msi;
|
||||||
if (!info->msi_capable)
|
if (!info->msi_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -284,7 +283,7 @@ pci_read_msi_info(PCIDev *device)
|
|||||||
if (!msi_supported())
|
if (!msi_supported())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
msi_info *info = &device->arch_info.msi;
|
msi_info *info = &device->msi;
|
||||||
info->msi_capable = false;
|
info->msi_capable = false;
|
||||||
status_t result = gPCI->FindCapability(device->domain, device->bus,
|
status_t result = gPCI->FindCapability(device->domain, device->bus,
|
||||||
device->device, device->function, PCI_cap_id_msi,
|
device->device, device->function, PCI_cap_id_msi,
|
||||||
@@ -319,7 +318,7 @@ pci_get_msix_count(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
msix_info *info = &device->arch_info.msix;
|
msix_info *info = &device->msix;
|
||||||
if (!info->msix_capable)
|
if (!info->msix_capable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -347,7 +346,7 @@ pci_configure_msix(uint8 virtualBus, uint8 _device, uint8 function,
|
|||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
msix_info *info = &device->arch_info.msix;
|
msix_info *info = &device->msix;
|
||||||
if (!info->msix_capable)
|
if (!info->msix_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -432,7 +431,7 @@ pci_configure_msix(uint8 virtualBus, uint8 _device, uint8 function,
|
|||||||
static status_t
|
static status_t
|
||||||
pci_unconfigure_msix(PCIDev *device)
|
pci_unconfigure_msix(PCIDev *device)
|
||||||
{
|
{
|
||||||
msix_info *info = &device->arch_info.msix;
|
msix_info *info = &device->msix;
|
||||||
if (!info->msix_capable)
|
if (!info->msix_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -481,7 +480,7 @@ pci_enable_msix(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
msix_info *info = &device->arch_info.msix;
|
msix_info *info = &device->msix;
|
||||||
if (!info->msix_capable)
|
if (!info->msix_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -509,7 +508,7 @@ pci_enable_msix(uint8 virtualBus, uint8 _device, uint8 function)
|
|||||||
status_t
|
status_t
|
||||||
pci_disable_msix(PCIDev *device)
|
pci_disable_msix(PCIDev *device)
|
||||||
{
|
{
|
||||||
msix_info *info = &device->arch_info.msix;
|
msix_info *info = &device->msix;
|
||||||
if (!info->msix_capable)
|
if (!info->msix_capable)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -534,7 +533,7 @@ pci_read_msix_info(PCIDev *device)
|
|||||||
if (!msi_supported())
|
if (!msi_supported())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
msix_info *info = &device->arch_info.msix;
|
msix_info *info = &device->msix;
|
||||||
info->msix_capable = false;
|
info->msix_capable = false;
|
||||||
status_t result = gPCI->FindCapability(device->domain, device->bus,
|
status_t result = gPCI->FindCapability(device->domain, device->bus,
|
||||||
device->device, device->function, PCI_cap_id_msix,
|
device->device, device->function, PCI_cap_id_msix,
|
||||||
@@ -28,6 +28,8 @@ KernelMergeObject kernel_arch_arm.o :
|
|||||||
arch_vm_translation_map.cpp
|
arch_vm_translation_map.cpp
|
||||||
arch_asm.S
|
arch_asm.S
|
||||||
|
|
||||||
|
generic_msi.cpp
|
||||||
|
|
||||||
# Serial UART and drivers
|
# Serial UART and drivers
|
||||||
debug_uart.cpp
|
debug_uart.cpp
|
||||||
debug_uart_8250.cpp
|
debug_uart_8250.cpp
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ KernelMergeObject kernel_arch_arm64.o :
|
|||||||
VMSAv8TranslationMap.cpp
|
VMSAv8TranslationMap.cpp
|
||||||
PMAPPhysicalPageMapper.cpp
|
PMAPPhysicalPageMapper.cpp
|
||||||
|
|
||||||
|
generic_msi.cpp
|
||||||
|
|
||||||
# Serial UART and drivers
|
# Serial UART and drivers
|
||||||
debug_uart.cpp
|
debug_uart.cpp
|
||||||
debug_uart_8250.cpp
|
debug_uart_8250.cpp
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <arch/generic/msi.h>
|
||||||
|
|
||||||
|
|
||||||
|
MSIInterface* sMSIInterface;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
msi_set_interface(MSIInterface* interface)
|
||||||
|
{
|
||||||
|
sMSIInterface = interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
msi_supported()
|
||||||
|
{
|
||||||
|
return sMSIInterface != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
msi_allocate_vectors(uint8 count, uint8 *startVector, uint64 *address, uint16 *data)
|
||||||
|
{
|
||||||
|
return sMSIInterface->AllocateVectors(count, *startVector, *address, *data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
msi_free_vectors(uint8 count, uint8 startVector)
|
||||||
|
{
|
||||||
|
sMSIInterface->FreeVectors(count, startVector);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -27,6 +27,8 @@ KernelMergeObject kernel_arch_riscv64.o :
|
|||||||
Htif.cpp
|
Htif.cpp
|
||||||
sbi_syscalls.S
|
sbi_syscalls.S
|
||||||
|
|
||||||
|
generic_msi.cpp
|
||||||
|
|
||||||
# Serial UART drivers
|
# Serial UART drivers
|
||||||
debug_uart.cpp
|
debug_uart.cpp
|
||||||
debug_uart_8250.cpp
|
debug_uart_8250.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user