AHCI: add MSI support.
This commit is contained in:
committed by
Jérôme Duval
parent
656e05ec86
commit
c01fadcadb
@@ -142,6 +142,7 @@ const device_info kSupportedDevices[] = {
|
||||
|
||||
device_manager_info *gDeviceManager;
|
||||
scsi_for_sim_interface *gSCSI;
|
||||
pci_x86_module_info* gPCIx86Module;
|
||||
|
||||
|
||||
status_t
|
||||
@@ -328,7 +329,17 @@ std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
if (get_module(B_PCI_X86_MODULE_NAME,
|
||||
(module_info**)&gPCIx86Module) != B_OK) {
|
||||
TRACE("failed to get pci x86 module\n");
|
||||
gPCIx86Module = NULL;
|
||||
}
|
||||
return B_OK;
|
||||
case B_MODULE_UNINIT:
|
||||
if (gPCIx86Module != NULL) {
|
||||
put_module(B_PCI_X86_MODULE_NAME);
|
||||
gPCIx86Module = NULL;
|
||||
}
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
|
||||
@@ -29,6 +29,7 @@ AHCIController::AHCIController(device_node *node,
|
||||
fPortCount(0),
|
||||
fPortImplementedMask(0),
|
||||
fIRQ(0),
|
||||
fUseMSI(false),
|
||||
fInstanceCheck(-1)
|
||||
{
|
||||
memset(fPort, 0, sizeof(fPort));
|
||||
@@ -101,6 +102,20 @@ AHCIController::Init()
|
||||
}
|
||||
|
||||
fIRQ = pciInfo.u.h0.interrupt_line;
|
||||
if (gPCIx86Module != NULL && gPCIx86Module->get_msi_count(
|
||||
pciInfo.bus, pciInfo.device, pciInfo.function) >= 1) {
|
||||
uint8 vector;
|
||||
if (gPCIx86Module->configure_msi(pciInfo.bus, pciInfo.device,
|
||||
pciInfo.function, 1, &vector) == B_OK
|
||||
&& gPCIx86Module->enable_msi(pciInfo.bus, pciInfo.device,
|
||||
pciInfo.function) == B_OK) {
|
||||
TRACE("using MSI vector %u\n", vector);
|
||||
fIRQ = vector;
|
||||
fUseMSI = true;
|
||||
} else {
|
||||
TRACE("couldn't use MSI\n");
|
||||
}
|
||||
}
|
||||
if (fIRQ == 0 || fIRQ == 0xff) {
|
||||
TRACE("Error: PCI IRQ not assigned\n");
|
||||
return B_ERROR;
|
||||
@@ -250,6 +265,15 @@ AHCIController::Uninit()
|
||||
// well...
|
||||
remove_io_interrupt_handler(fIRQ, Interrupt, this);
|
||||
|
||||
if (fUseMSI && gPCIx86Module != NULL) {
|
||||
pci_info pciInfo;
|
||||
fPCI->get_pci_info(fPCIDevice, &pciInfo);
|
||||
gPCIx86Module->disable_msi(pciInfo.bus,
|
||||
pciInfo.device, pciInfo.function);
|
||||
gPCIx86Module->unconfigure_msi(pciInfo.bus,
|
||||
pciInfo.device, pciInfo.function);
|
||||
}
|
||||
|
||||
delete_area(fRegsArea);
|
||||
|
||||
// --- Instance check workaround begin
|
||||
|
||||
@@ -52,6 +52,7 @@ private:
|
||||
int fPortCount;
|
||||
uint32 fPortImplementedMask;
|
||||
uint8 fIRQ;
|
||||
bool fUseMSI;
|
||||
AHCIPort * fPort[32];
|
||||
|
||||
// --- Instance check workaround begin
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <bus/PCI.h>
|
||||
#include <bus/SCSI.h>
|
||||
#include <PCI_x86.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -259,6 +260,7 @@ status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name,
|
||||
extern scsi_sim_interface gAHCISimInterface;
|
||||
extern device_manager_info *gDeviceManager;
|
||||
extern scsi_for_sim_interface *gSCSI;
|
||||
extern pci_x86_module_info* gPCIx86Module;
|
||||
|
||||
|
||||
#define MAX_SECTOR_LBA_28 ((1ull << 28) - 1)
|
||||
|
||||
Reference in New Issue
Block a user