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;
|
device_manager_info *gDeviceManager;
|
||||||
scsi_for_sim_interface *gSCSI;
|
scsi_for_sim_interface *gSCSI;
|
||||||
|
pci_x86_module_info* gPCIx86Module;
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -328,7 +329,17 @@ std_ops(int32 op, ...)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case B_MODULE_INIT:
|
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:
|
case B_MODULE_UNINIT:
|
||||||
|
if (gPCIx86Module != NULL) {
|
||||||
|
put_module(B_PCI_X86_MODULE_NAME);
|
||||||
|
gPCIx86Module = NULL;
|
||||||
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ AHCIController::AHCIController(device_node *node,
|
|||||||
fPortCount(0),
|
fPortCount(0),
|
||||||
fPortImplementedMask(0),
|
fPortImplementedMask(0),
|
||||||
fIRQ(0),
|
fIRQ(0),
|
||||||
|
fUseMSI(false),
|
||||||
fInstanceCheck(-1)
|
fInstanceCheck(-1)
|
||||||
{
|
{
|
||||||
memset(fPort, 0, sizeof(fPort));
|
memset(fPort, 0, sizeof(fPort));
|
||||||
@@ -101,6 +102,20 @@ AHCIController::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
fIRQ = pciInfo.u.h0.interrupt_line;
|
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) {
|
if (fIRQ == 0 || fIRQ == 0xff) {
|
||||||
TRACE("Error: PCI IRQ not assigned\n");
|
TRACE("Error: PCI IRQ not assigned\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -250,6 +265,15 @@ AHCIController::Uninit()
|
|||||||
// well...
|
// well...
|
||||||
remove_io_interrupt_handler(fIRQ, Interrupt, this);
|
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);
|
delete_area(fRegsArea);
|
||||||
|
|
||||||
// --- Instance check workaround begin
|
// --- Instance check workaround begin
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ private:
|
|||||||
int fPortCount;
|
int fPortCount;
|
||||||
uint32 fPortImplementedMask;
|
uint32 fPortImplementedMask;
|
||||||
uint8 fIRQ;
|
uint8 fIRQ;
|
||||||
|
bool fUseMSI;
|
||||||
AHCIPort * fPort[32];
|
AHCIPort * fPort[32];
|
||||||
|
|
||||||
// --- Instance check workaround begin
|
// --- Instance check workaround begin
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <bus/PCI.h>
|
#include <bus/PCI.h>
|
||||||
#include <bus/SCSI.h>
|
#include <bus/SCSI.h>
|
||||||
|
#include <PCI_x86.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -259,6 +260,7 @@ status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name,
|
|||||||
extern scsi_sim_interface gAHCISimInterface;
|
extern scsi_sim_interface gAHCISimInterface;
|
||||||
extern device_manager_info *gDeviceManager;
|
extern device_manager_info *gDeviceManager;
|
||||||
extern scsi_for_sim_interface *gSCSI;
|
extern scsi_for_sim_interface *gSCSI;
|
||||||
|
extern pci_x86_module_info* gPCIx86Module;
|
||||||
|
|
||||||
|
|
||||||
#define MAX_SECTOR_LBA_28 ((1ull << 28) - 1)
|
#define MAX_SECTOR_LBA_28 ((1ull << 28) - 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user