* Add the framework for adding an arch specific module to the PCI bus_manager.
* Implement such a module for x86 which currently exports only an MSI API. * Implement the PCI part for configuring and enabling MSIs. * Some automatic whitespace cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36223 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -83,7 +83,7 @@ typedef struct pci_info {
|
|||||||
ulong rom_base_pci; /* rom base addr, viewed from pci */
|
ulong rom_base_pci; /* rom base addr, viewed from pci */
|
||||||
uchar interrupt_line; /* interrupt line */
|
uchar interrupt_line; /* interrupt line */
|
||||||
uchar interrupt_pin; /* interrupt pin */
|
uchar interrupt_pin; /* interrupt pin */
|
||||||
ushort bridge_control;
|
ushort bridge_control;
|
||||||
ushort subsystem_id; /* subsystem (add-in card) id */
|
ushort subsystem_id; /* subsystem (add-in card) id */
|
||||||
ushort subsystem_vendor_id; /* subsystem (add-in card) vendor id */
|
ushort subsystem_vendor_id; /* subsystem (add-in card) vendor id */
|
||||||
} h1;
|
} h1;
|
||||||
@@ -109,7 +109,7 @@ typedef struct pci_info {
|
|||||||
ushort secondary_status;
|
ushort secondary_status;
|
||||||
ushort bridge_control;
|
ushort bridge_control;
|
||||||
#endif /* __HAIKU_PCI_BUS_MANAGER_TESTING */
|
#endif /* __HAIKU_PCI_BUS_MANAGER_TESTING */
|
||||||
} h2;
|
} h2;
|
||||||
} u;
|
} u;
|
||||||
} pci_info;
|
} pci_info;
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ struct pci_module_info {
|
|||||||
#define PCI_primary_bus 0x18 /* (1 byte) */
|
#define PCI_primary_bus 0x18 /* (1 byte) */
|
||||||
#define PCI_secondary_bus 0x19 /* (1 byte) */
|
#define PCI_secondary_bus 0x19 /* (1 byte) */
|
||||||
#define PCI_subordinate_bus 0x1A /* (1 byte) */
|
#define PCI_subordinate_bus 0x1A /* (1 byte) */
|
||||||
#define PCI_secondary_latency 0x1B /* (1 byte) latency of secondary bus */
|
#define PCI_secondary_latency 0x1B /* (1 byte) latency of secondary bus */
|
||||||
#define PCI_io_base 0x1C /* (1 byte) io base address register for 2ndry bus*/
|
#define PCI_io_base 0x1C /* (1 byte) io base address register for 2ndry bus*/
|
||||||
#define PCI_io_limit 0x1D /* (1 byte) */
|
#define PCI_io_limit 0x1D /* (1 byte) */
|
||||||
#define PCI_secondary_status 0x1E /* (2 bytes) */
|
#define PCI_secondary_status 0x1E /* (2 bytes) */
|
||||||
@@ -236,7 +236,7 @@ struct pci_module_info {
|
|||||||
#define PCI_sub_vendor_id_1 0x34 /* (2 bytes) */
|
#define PCI_sub_vendor_id_1 0x34 /* (2 bytes) */
|
||||||
#define PCI_sub_device_id_1 0x36 /* (2 bytes) */
|
#define PCI_sub_device_id_1 0x36 /* (2 bytes) */
|
||||||
#define PCI_bridge_rom_base 0x38
|
#define PCI_bridge_rom_base 0x38
|
||||||
#define PCI_bridge_control 0x3E /* (2 bytes) */
|
#define PCI_bridge_control 0x3E /* (2 bytes) */
|
||||||
|
|
||||||
|
|
||||||
/* PCI type 2 header offsets */
|
/* PCI type 2 header offsets */
|
||||||
@@ -245,7 +245,7 @@ struct pci_module_info {
|
|||||||
#define PCI_primary_bus_2 0x18 /* (1 byte) */
|
#define PCI_primary_bus_2 0x18 /* (1 byte) */
|
||||||
#define PCI_secondary_bus_2 0x19 /* (1 byte) */
|
#define PCI_secondary_bus_2 0x19 /* (1 byte) */
|
||||||
#define PCI_subordinate_bus_2 0x1A /* (1 byte) */
|
#define PCI_subordinate_bus_2 0x1A /* (1 byte) */
|
||||||
#define PCI_secondary_latency_2 0x1B /* (1 byte) latency of secondary bus */
|
#define PCI_secondary_latency_2 0x1B /* (1 byte) latency of secondary bus */
|
||||||
#define PCI_memory_base0_2 0x1C /* (4 bytes) */
|
#define PCI_memory_base0_2 0x1C /* (4 bytes) */
|
||||||
#define PCI_memory_limit0_2 0x20 /* (4 bytes) */
|
#define PCI_memory_limit0_2 0x20 /* (4 bytes) */
|
||||||
#define PCI_memory_base1_2 0x24 /* (4 bytes) */
|
#define PCI_memory_base1_2 0x24 /* (4 bytes) */
|
||||||
@@ -588,8 +588,8 @@ struct pci_module_info {
|
|||||||
|
|
||||||
/** types of PCI header */
|
/** types of PCI header */
|
||||||
|
|
||||||
#define PCI_header_type_generic 0x00
|
#define PCI_header_type_generic 0x00
|
||||||
#define PCI_header_type_PCI_to_PCI_bridge 0x01
|
#define PCI_header_type_PCI_to_PCI_bridge 0x01
|
||||||
#define PCI_header_type_cardbus 0x02
|
#define PCI_header_type_cardbus 0x02
|
||||||
|
|
||||||
|
|
||||||
@@ -677,6 +677,34 @@ struct pci_module_info {
|
|||||||
#define PCI_pm_state_d2 0x02
|
#define PCI_pm_state_d2 0x02
|
||||||
#define PCI_pm_state_d3 0x03
|
#define PCI_pm_state_d3 0x03
|
||||||
|
|
||||||
|
/** MSI registers **/
|
||||||
|
#define PCI_msi_control 0x02
|
||||||
|
#define PCI_msi_address 0x04
|
||||||
|
#define PCI_msi_address_high 0x08
|
||||||
|
#define PCI_msi_data 0x08
|
||||||
|
#define PCI_msi_data_64bit 0x0c
|
||||||
|
#define PCI_msi_mask 0x10
|
||||||
|
#define PCI_msi_pending 0x14
|
||||||
|
|
||||||
|
/** MSI control register values **/
|
||||||
|
#define PCI_msi_control_enable 0x0001
|
||||||
|
#define PCI_msi_control_vector 0x0100
|
||||||
|
#define PCI_msi_control_64bit 0x0080
|
||||||
|
#define PCI_msi_control_mme_mask 0x0070
|
||||||
|
#define PCI_msi_control_mme_1 0x0000
|
||||||
|
#define PCI_msi_control_mme_2 0x0010
|
||||||
|
#define PCI_msi_control_mme_4 0x0020
|
||||||
|
#define PCI_msi_control_mme_8 0x0030
|
||||||
|
#define PCI_msi_control_mme_16 0x0040
|
||||||
|
#define PCI_msi_control_mme_32 0x0050
|
||||||
|
#define PCI_msi_control_mmc_mask 0x000e
|
||||||
|
#define PCI_msi_control_mmc_1 0x0000
|
||||||
|
#define PCI_msi_control_mmc_2 0x0002
|
||||||
|
#define PCI_msi_control_mmc_4 0x0004
|
||||||
|
#define PCI_msi_control_mmc_8 0x0006
|
||||||
|
#define PCI_msi_control_mmc_16 0x0008
|
||||||
|
#define PCI_msi_control_mmc_32 0x000a
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef PCI_X86_H
|
||||||
|
#define PCI_X86_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <module.h>
|
||||||
|
|
||||||
|
typedef struct pci_x86_module_info {
|
||||||
|
module_info info;
|
||||||
|
|
||||||
|
uint8 (*get_msi_count)(
|
||||||
|
uint8 bus, /* bus number */
|
||||||
|
uint8 device, /* device # on bus */
|
||||||
|
uint8 function); /* function # in device */
|
||||||
|
|
||||||
|
status_t (*configure_msi)(
|
||||||
|
uint8 bus, /* bus number */
|
||||||
|
uint8 device, /* device # on bus */
|
||||||
|
uint8 function, /* function # in device */
|
||||||
|
uint8 count, /* count of vectors desired */
|
||||||
|
uint8 *startVector); /* first configured vector */
|
||||||
|
status_t (*unconfigure_msi)(
|
||||||
|
uint8 bus, /* bus number */
|
||||||
|
uint8 device, /* device # on bus */
|
||||||
|
uint8 function); /* function # in device */
|
||||||
|
|
||||||
|
status_t (*enable_msi)(
|
||||||
|
uint8 bus, /* bus number */
|
||||||
|
uint8 device, /* device # on bus */
|
||||||
|
uint8 function); /* function # in device */
|
||||||
|
status_t (*disable_msi)(
|
||||||
|
uint8 bus, /* bus number */
|
||||||
|
uint8 device, /* device # on bus */
|
||||||
|
uint8 function); /* function # in device */
|
||||||
|
} pci_x86_module_info;
|
||||||
|
|
||||||
|
#define B_PCI_X86_MODULE_NAME "bus_managers/pci/x86/v1"
|
||||||
|
|
||||||
|
#endif // PCI_X86_H
|
||||||
@@ -3,12 +3,13 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers pci ;
|
|||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
UsePrivateHeaders [ FDirName kernel util ] ;
|
UsePrivateHeaders [ FDirName kernel util ] ;
|
||||||
|
UseHeaders [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
|
||||||
|
|
||||||
KernelAddon pci :
|
KernelAddon pci :
|
||||||
pci.cpp
|
pci.cpp
|
||||||
pci_fixup.cpp
|
pci_fixup.cpp
|
||||||
pci_info.cpp
|
pci_info.cpp
|
||||||
pci_module.c
|
pci_module.cpp
|
||||||
pci_root.cpp
|
pci_root.cpp
|
||||||
pci_device.cpp
|
pci_device.cpp
|
||||||
: pci_arch_bus_manager.a
|
: pci_arch_bus_manager.a
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers pci arch x86 ;
|
|||||||
|
|
||||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||||
|
|
||||||
UsePrivateHeaders kernel [ FDirName kernel arch x86 ] ;
|
UsePrivateHeaders kernel [ FDirName kernel arch x86 ] [ FDirName kernel util ] ;
|
||||||
|
|
||||||
KernelStaticLibrary pci_arch_bus_manager :
|
KernelStaticLibrary pci_arch_bus_manager :
|
||||||
|
pci_arch_info.cpp
|
||||||
|
pci_arch_module.cpp
|
||||||
pci_bios.c
|
pci_bios.c
|
||||||
pci_controller.c
|
pci_controller.c
|
||||||
pci_io.c
|
pci_io.c
|
||||||
pci_irq.c
|
pci_irq.c
|
||||||
|
pci_msi.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include "pci_arch_info.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
pci_read_arch_info(PCIDev *dev)
|
||||||
|
{
|
||||||
|
pci_read_msi_info(dev);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _PCI_ARCH_INFO_H
|
||||||
|
#define _PCI_ARCH_INFO_H
|
||||||
|
|
||||||
|
#include "pci_msi.h"
|
||||||
|
|
||||||
|
typedef struct pci_arch_info {
|
||||||
|
msi_info msi;
|
||||||
|
} pci_arch_info;
|
||||||
|
|
||||||
|
|
||||||
|
void pci_read_arch_info(PCIDev *device);
|
||||||
|
|
||||||
|
#endif // _PCI_ARCH_INFO_H
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include <PCI_x86.h>
|
||||||
|
#include "pci_msi.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int32
|
||||||
|
pci_arch_module_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
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
|
||||||
|
};
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
#include "pci_msi.h"
|
||||||
|
#include "pci_arch_info.h"
|
||||||
|
#include "pci.h"
|
||||||
|
#include "pci_private.h"
|
||||||
|
|
||||||
|
#include <arch/x86/msi.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
extern PCI *gPCI;
|
||||||
|
|
||||||
|
|
||||||
|
uint8
|
||||||
|
pci_get_msi_count(uint8 virtualBus, uint8 _device, uint8 function)
|
||||||
|
{
|
||||||
|
if (!msi_supported())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint8 bus;
|
||||||
|
int domain;
|
||||||
|
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PCIDev *device = gPCI->FindDevice(domain, bus, _device, function);
|
||||||
|
if (device == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
msi_info *info = &device->arch_info.msi;
|
||||||
|
if (!info->msi_capable)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return info->message_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
pci_configure_msi(uint8 virtualBus, uint8 _device, uint8 function,
|
||||||
|
uint8 count, uint8 *startVector)
|
||||||
|
{
|
||||||
|
if (!msi_supported())
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (count == 0 || startVector == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
uint8 bus;
|
||||||
|
int domain;
|
||||||
|
status_t result = gPCI->ResolveVirtualBus(virtualBus, &domain, &bus);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
PCIDev *device = gPCI->FindDevice(domain, bus, _device, function);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
msi_info *info = &device->arch_info.msi;
|
||||||
|
if (!info->msi_capable)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (count > 32 || count > info->message_count
|
||||||
|
|| ((count - 1) & count) != 0 /* needs to be a power of 2 */) {
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->configured_count != 0)
|
||||||
|
return B_BUSY;
|
||||||
|
|
||||||
|
result = msi_allocate_vectors(count, &info->start_vector,
|
||||||
|
&info->address_value, &info->data_value);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
uint8 offset = info->capability_offset;
|
||||||
|
gPCI->WriteConfig(device, offset + PCI_msi_address, 4,
|
||||||
|
info->address_value & 0xffffffff);
|
||||||
|
if (info->control_value & PCI_msi_control_64bit) {
|
||||||
|
gPCI->WriteConfig(device, offset + PCI_msi_address_high, 4,
|
||||||
|
info->address_value >> 32);
|
||||||
|
gPCI->WriteConfig(device, offset + PCI_msi_data_64bit, 2,
|
||||||
|
info->data_value);
|
||||||
|
} else
|
||||||
|
gPCI->WriteConfig(device, offset + PCI_msi_data, 2, info->data_value);
|
||||||
|
|
||||||
|
info->control_value &= ~PCI_msi_control_mme_mask;
|
||||||
|
info->control_value |= (ffs(count) - 1) << 4;
|
||||||
|
gPCI->WriteConfig(device, offset + PCI_msi_control, 2, info->control_value);
|
||||||
|
|
||||||
|
info->configured_count = count;
|
||||||
|
*startVector = info->start_vector;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
pci_unconfigure_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
||||||
|
{
|
||||||
|
if (!msi_supported())
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
uint8 bus;
|
||||||
|
int domain;
|
||||||
|
status_t result = gPCI->ResolveVirtualBus(virtualBus, &domain, &bus);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
PCIDev *device = gPCI->FindDevice(domain, bus, _device, function);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
msi_info *info = &device->arch_info.msi;
|
||||||
|
if (!info->msi_capable)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (info->configured_count == 0)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
msi_free_vectors(info->configured_count, info->start_vector);
|
||||||
|
|
||||||
|
info->control_value &= ~PCI_msi_control_mme_mask;
|
||||||
|
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
|
||||||
|
info->control_value);
|
||||||
|
|
||||||
|
info->configured_count = 0;
|
||||||
|
info->address_value = 0;
|
||||||
|
info->data_value = 0;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
pci_enable_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
||||||
|
{
|
||||||
|
if (!msi_supported())
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
uint8 bus;
|
||||||
|
int domain;
|
||||||
|
status_t result = gPCI->ResolveVirtualBus(virtualBus, &domain, &bus);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
PCIDev *device = gPCI->FindDevice(domain, bus, _device, function);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
msi_info *info = &device->arch_info.msi;
|
||||||
|
if (!info->msi_capable)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (info->configured_count == 0)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
// ensure the pinned interrupt is disabled
|
||||||
|
gPCI->WriteConfig(device, PCI_command, 2,
|
||||||
|
gPCI->ReadConfig(device, PCI_command, 2) | PCI_command_int_disable);
|
||||||
|
|
||||||
|
// enable msi generation
|
||||||
|
info->control_value |= PCI_msi_control_enable;
|
||||||
|
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
|
||||||
|
info->control_value);
|
||||||
|
|
||||||
|
dprintf("msi enabled: 0x%04lx\n",
|
||||||
|
gPCI->ReadConfig(device, info->capability_offset + PCI_msi_control, 2));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
pci_disable_msi(uint8 virtualBus, uint8 _device, uint8 function)
|
||||||
|
{
|
||||||
|
if (!msi_supported())
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
uint8 bus;
|
||||||
|
int domain;
|
||||||
|
status_t result = gPCI->ResolveVirtualBus(virtualBus, &domain, &bus);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
PCIDev *device = gPCI->FindDevice(domain, bus, _device, function);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
msi_info *info = &device->arch_info.msi;
|
||||||
|
if (!info->msi_capable)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (info->configured_count == 0)
|
||||||
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
// disable msi generation
|
||||||
|
info->control_value &= ~PCI_msi_control_enable;
|
||||||
|
gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2,
|
||||||
|
info->control_value);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
pci_read_msi_info(PCIDev *device)
|
||||||
|
{
|
||||||
|
if (!msi_supported())
|
||||||
|
return;
|
||||||
|
|
||||||
|
msi_info *info = &device->arch_info.msi;
|
||||||
|
info->msi_capable = false;
|
||||||
|
status_t result = gPCI->FindCapability(device->domain, device->bus,
|
||||||
|
device->device, device->function, PCI_cap_id_msi,
|
||||||
|
&info->capability_offset);
|
||||||
|
if (result != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
info->msi_capable = true;
|
||||||
|
info->control_value = gPCI->ReadConfig(device->domain, device->bus,
|
||||||
|
device->device, device->function,
|
||||||
|
info->capability_offset + PCI_msi_control, 2);
|
||||||
|
info->message_count
|
||||||
|
= 1 << ((info->control_value & PCI_msi_control_mmc_mask) >> 1);
|
||||||
|
info->configured_count = 0;
|
||||||
|
info->data_value = 0;
|
||||||
|
info->address_value = 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _PCI_x86_MSI_H
|
||||||
|
#define _PCI_x86_MSI_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
class PCIDev;
|
||||||
|
|
||||||
|
// Message Signaled Interrupts
|
||||||
|
typedef struct msi_info {
|
||||||
|
bool msi_capable;
|
||||||
|
uint8 capability_offset;
|
||||||
|
uint8 message_count;
|
||||||
|
uint8 configured_count;
|
||||||
|
uint8 start_vector;
|
||||||
|
uint16 control_value;
|
||||||
|
uint16 data_value;
|
||||||
|
uint64 address_value;
|
||||||
|
} msi_info;
|
||||||
|
|
||||||
|
|
||||||
|
uint8 pci_get_msi_count(uint8 virtualBus, uint8 _device, uint8 function);
|
||||||
|
status_t pci_configure_msi(uint8 virtualBus, uint8 _device, uint8 function,
|
||||||
|
uint8 count, uint8 *startVector);
|
||||||
|
status_t pci_unconfigure_msi(uint8 virtualBus, uint8 device, uint8 function);
|
||||||
|
status_t pci_enable_msi(uint8 virtualBus, uint8 device, uint8 function);
|
||||||
|
status_t pci_disable_msi(uint8 virtualBus, uint8 device, uint8 function);
|
||||||
|
void pci_read_msi_info(PCIDev *device);
|
||||||
|
|
||||||
|
#endif // _PCI_x86_MSI_H
|
||||||
@@ -103,7 +103,7 @@ pci_reserve_device(uchar virtualBus, uchar device, uchar function,
|
|||||||
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
|
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
//TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
|
//TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
|
||||||
// domain, bus, device, function, driverName, nodeCookie));
|
// domain, bus, device, function, driverName, nodeCookie));
|
||||||
|
|
||||||
device_attr matchPCIRoot[] = {
|
device_attr matchPCIRoot[] = {
|
||||||
@@ -140,7 +140,7 @@ pci_reserve_device(uchar virtualBus, uchar device, uchar function,
|
|||||||
root = gDeviceManager->get_root_node();
|
root = gDeviceManager->get_root_node();
|
||||||
if (!root)
|
if (!root)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
pci = NULL;
|
pci = NULL;
|
||||||
if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK)
|
if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK)
|
||||||
goto err0;
|
goto err0;
|
||||||
@@ -148,16 +148,16 @@ pci_reserve_device(uchar virtualBus, uchar device, uchar function,
|
|||||||
node = NULL;
|
node = NULL;
|
||||||
if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK)
|
if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
// common API for all legacy modules ?
|
// common API for all legacy modules ?
|
||||||
//status = legacy_driver_register(node, driverName, nodeCookie, PCI_LEGACY_DRIVER_MODULE_NAME);
|
//status = legacy_driver_register(node, driverName, nodeCookie, PCI_LEGACY_DRIVER_MODULE_NAME);
|
||||||
|
|
||||||
status = gDeviceManager->register_node(node, PCI_LEGACY_DRIVER_MODULE_NAME,
|
status = gDeviceManager->register_node(node, PCI_LEGACY_DRIVER_MODULE_NAME,
|
||||||
legacyAttrs, NULL, &legacy);
|
legacyAttrs, NULL, &legacy);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
status = gDeviceManager->register_node(legacy, PCI_LEGACY_DRIVER_MODULE_NAME,
|
status = gDeviceManager->register_node(legacy, PCI_LEGACY_DRIVER_MODULE_NAME,
|
||||||
drvAttrs, NULL, NULL);
|
drvAttrs, NULL, NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err3;
|
goto err3;
|
||||||
@@ -192,7 +192,7 @@ pci_unreserve_device(uchar virtualBus, uchar device, uchar function,
|
|||||||
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
|
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
//TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
|
//TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
|
||||||
// domain, bus, device, function, driverName, nodeCookie));
|
// domain, bus, device, function, driverName, nodeCookie));
|
||||||
|
|
||||||
device_attr matchPCIRoot[] = {
|
device_attr matchPCIRoot[] = {
|
||||||
@@ -237,7 +237,7 @@ pci_unreserve_device(uchar virtualBus, uchar device, uchar function,
|
|||||||
node = NULL;
|
node = NULL;
|
||||||
if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK)
|
if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
// common API for all legacy modules ?
|
// common API for all legacy modules ?
|
||||||
//status = legacy_driver_unregister(node, driverName, nodeCookie);
|
//status = legacy_driver_unregister(node, driverName, nodeCookie);
|
||||||
|
|
||||||
@@ -1325,6 +1325,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);
|
||||||
|
#ifdef __INTEL__
|
||||||
|
pci_read_arch_info(dev);
|
||||||
|
#endif
|
||||||
if (dev->child)
|
if (dev->child)
|
||||||
_RefreshDeviceInfo(dev->child);
|
_RefreshDeviceInfo(dev->child);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
#include "pci_controller.h"
|
#include "pci_controller.h"
|
||||||
|
|
||||||
|
#ifdef __INTEL__
|
||||||
|
#include "pci_arch_info.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TRACE_PCI
|
#define TRACE_PCI
|
||||||
#ifndef TRACE_PCI
|
#ifndef TRACE_PCI
|
||||||
@@ -23,7 +26,6 @@
|
|||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
struct PCIDev;
|
struct PCIDev;
|
||||||
@@ -45,6 +47,9 @@ struct PCIDev {
|
|||||||
uint8 device;
|
uint8 device;
|
||||||
uint8 function;
|
uint8 function;
|
||||||
pci_info info;
|
pci_info info;
|
||||||
|
#ifdef __INTEL__
|
||||||
|
pci_arch_info arch_info;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <PCI.h>
|
||||||
|
|
||||||
|
#include "pci_private.h"
|
||||||
|
#include "pci_info.h"
|
||||||
|
#include "pci.h"
|
||||||
|
|
||||||
|
|
||||||
|
device_manager_info *gDeviceManager;
|
||||||
|
extern struct pci_arch_module gPCIArchModule;
|
||||||
|
|
||||||
|
static int32
|
||||||
|
pci_old_module_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
TRACE(("PCI: pci_module_init\n"));
|
||||||
|
|
||||||
|
status = pci_init();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
pci_print_info();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
TRACE(("PCI: pci_module_uninit\n"));
|
||||||
|
pci_uninit();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct pci_module_info sOldPCIModule = {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
B_PCI_MODULE_NAME,
|
||||||
|
B_KEEP_LOADED,
|
||||||
|
pci_old_module_std_ops
|
||||||
|
},
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
&pci_read_io_8,
|
||||||
|
&pci_write_io_8,
|
||||||
|
&pci_read_io_16,
|
||||||
|
&pci_write_io_16,
|
||||||
|
&pci_read_io_32,
|
||||||
|
&pci_write_io_32,
|
||||||
|
&pci_get_nth_pci_info,
|
||||||
|
&pci_read_config,
|
||||||
|
&pci_write_config,
|
||||||
|
&pci_ram_address,
|
||||||
|
&pci_find_capability,
|
||||||
|
&pci_reserve_device,
|
||||||
|
&pci_unreserve_device
|
||||||
|
};
|
||||||
|
|
||||||
|
module_dependency module_dependencies[] = {
|
||||||
|
{B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
driver_module_info gPCILegacyDriverModule = {
|
||||||
|
{
|
||||||
|
PCI_LEGACY_DRIVER_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
module_info *modules[] = {
|
||||||
|
(module_info *)&sOldPCIModule,
|
||||||
|
(module_info *)&gPCIRootModule,
|
||||||
|
(module_info *)&gPCIDeviceModule,
|
||||||
|
(module_info *)&gPCILegacyDriverModule,
|
||||||
|
#ifdef __INTEL__
|
||||||
|
// add platforms when they provide an arch specific module
|
||||||
|
(module_info *)&gPCIArchModule,
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user