UHCI USB: add MSI support

* similar to OHCI support by mmlr.
* interrupt handler is removed on destruction.
This commit is contained in:
Jerome Duval 2013-07-31 00:12:23 +02:00 committed by Jérôme Duval
parent b3dbb4d23b
commit c45ac5ad59
2 changed files with 38 additions and 3 deletions

View File

@ -10,6 +10,7 @@
#include <module.h> #include <module.h>
#include <PCI.h> #include <PCI.h>
#include <PCI_x86.h>
#include <USB3.h> #include <USB3.h>
#include <KernelExport.h> #include <KernelExport.h>
@ -18,6 +19,7 @@
#define USB_MODULE_NAME "uhci" #define USB_MODULE_NAME "uhci"
pci_module_info *UHCI::sPCIModule = NULL; pci_module_info *UHCI::sPCIModule = NULL;
pci_x86_module_info *UHCI::sPCIx86Module = NULL;
static int32 sDebuggerCommandAdded = 0; static int32 sDebuggerCommandAdded = 0;
@ -404,7 +406,9 @@ UHCI::UHCI(pci_info *info, Stack *stack)
fFinishIsochronousThread(-1), fFinishIsochronousThread(-1),
fRootHub(NULL), fRootHub(NULL),
fRootHubAddress(0), fRootHubAddress(0),
fPortResetChange(0) fPortResetChange(0),
fIRQ(0),
fUseMSI(false)
{ {
// Create a lock for the isochronous transfer list // Create a lock for the isochronous transfer list
mutex_init(&fIsochronousLock, "UHCI isochronous lock"); mutex_init(&fIsochronousLock, "UHCI isochronous lock");
@ -557,10 +561,24 @@ UHCI::UHCI(pci_info *info, Stack *stack)
(void *)this); (void *)this);
resume_thread(fFinishIsochronousThread); resume_thread(fFinishIsochronousThread);
// Find the right interrupt vector, using MSIs if available.
fIRQ = fPCIInfo->u.h0.interrupt_line;
if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
fPCIInfo->device, fPCIInfo->function) >= 1) {
uint8 msiVector = 0;
if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
fPCIInfo->function, 1, &msiVector) == B_OK
&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
fPCIInfo->function) == B_OK) {
TRACE_ALWAYS("using message signaled interrupts\n");
fIRQ = msiVector;
fUseMSI = true;
}
}
// Install the interrupt handler // Install the interrupt handler
TRACE("installing interrupt handler\n"); TRACE("installing interrupt handler\n");
install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line, install_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this, 0);
InterruptHandler, (void *)this, 0);
// Enable interrupts // Enable interrupts
fEnabledInterrupts = UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT fEnabledInterrupts = UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT
@ -599,6 +617,8 @@ UHCI::~UHCI()
wait_for_thread(fCleanupThread, &result); wait_for_thread(fCleanupThread, &result);
wait_for_thread(fFinishIsochronousThread, &result); wait_for_thread(fFinishIsochronousThread, &result);
remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
LockIsochronous(); LockIsochronous();
isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer; isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer;
while (isoTransfer) { while (isoTransfer) {
@ -629,7 +649,17 @@ UHCI::~UHCI()
delete fRootHub; delete fRootHub;
delete_area(fFrameArea); delete_area(fFrameArea);
if (fUseMSI && sPCIx86Module != NULL) {
sPCIx86Module->disable_msi(fPCIInfo->bus,
fPCIInfo->device, fPCIInfo->function);
sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
fPCIInfo->device, fPCIInfo->function);
}
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
if (sPCIx86Module != NULL) {
sPCIx86Module = NULL;
put_module(B_PCI_X86_MODULE_NAME);
}
Unlock(); Unlock();
} }

View File

@ -23,6 +23,7 @@
struct pci_info; struct pci_info;
struct pci_module_info; struct pci_module_info;
struct pci_x86_module_info;
class UHCIRootHub; class UHCIRootHub;
class DebugTransfer; class DebugTransfer;
@ -208,6 +209,7 @@ inline uint16 ReadReg16(uint32 reg);
inline uint32 ReadReg32(uint32 reg); inline uint32 ReadReg32(uint32 reg);
static pci_module_info * sPCIModule; static pci_module_info * sPCIModule;
static pci_x86_module_info * sPCIx86Module;
uint32 fRegisterBase; uint32 fRegisterBase;
pci_info * fPCIInfo; pci_info * fPCIInfo;
@ -256,6 +258,9 @@ static pci_module_info * sPCIModule;
UHCIRootHub * fRootHub; UHCIRootHub * fRootHub;
uint8 fRootHubAddress; uint8 fRootHubAddress;
uint8 fPortResetChange; uint8 fPortResetChange;
uint8 fIRQ;
bool fUseMSI;
}; };