Add MSI support to OHCI.

It looks like VirtualBox assumes MSIs when emulating a 64bit system so
this gets OHCI working there. Shouldn't harm if it's used anywhere else
either.
This commit is contained in:
Michael Lotz
2012-08-16 00:31:19 +02:00
parent c936a02360
commit a4bca81193
2 changed files with 41 additions and 2 deletions
+38 -2
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>
#include <util/AutoLock.h> #include <util/AutoLock.h>
@@ -19,6 +20,7 @@
#define USB_MODULE_NAME "ohci" #define USB_MODULE_NAME "ohci"
pci_module_info *OHCI::sPCIModule = NULL; pci_module_info *OHCI::sPCIModule = NULL;
pci_x86_module_info *OHCI::sPCIx86Module = NULL;
static int32 static int32
@@ -309,10 +311,24 @@ OHCI::OHCI(pci_info *info, Stack *stack)
B_URGENT_DISPLAY_PRIORITY, (void *)this); B_URGENT_DISPLAY_PRIORITY, (void *)this);
resume_thread(fFinishThread); resume_thread(fFinishThread);
// Find the right interrupt vector, using MSIs if available.
uint8 interruptVector = 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");
interruptVector = msiVector;
}
}
// 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(interruptVector, _InterruptHandler,
_InterruptHandler, (void *)this, 0); (void *)this, 0);
// Enable interesting interrupts now that the handler is in place // Enable interesting interrupts now that the handler is in place
_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS _WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
@@ -538,6 +554,14 @@ OHCI::AddTo(Stack *stack)
return B_NO_MEMORY; return B_NO_MEMORY;
} }
// Try to get the PCI x86 module as well so we can enable possible MSIs.
if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME,
(module_info **)&sPCIx86Module) != B_OK) {
// If it isn't there, that's not critical though.
TRACE_MODULE_ERROR("failed to get pci x86 module\n");
sPCIx86Module = NULL;
}
for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) { for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
&& item->class_api == PCI_usb_ohci) { && item->class_api == PCI_usb_ohci) {
@@ -555,6 +579,12 @@ OHCI::AddTo(Stack *stack)
delete item; delete item;
sPCIModule = NULL; sPCIModule = NULL;
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
if (sPCIx86Module != NULL) {
sPCIx86Module = NULL;
put_module(B_PCI_X86_MODULE_NAME);
}
return B_NO_MEMORY; return B_NO_MEMORY;
} }
@@ -578,6 +608,12 @@ OHCI::AddTo(Stack *stack)
delete item; delete item;
sPCIModule = NULL; sPCIModule = NULL;
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
if (sPCIx86Module != NULL) {
sPCIx86Module = NULL;
put_module(B_PCI_X86_MODULE_NAME);
}
return ENODEV; return ENODEV;
} }
+3
View File
@@ -16,6 +16,7 @@
struct pci_info; struct pci_info;
struct pci_module_info; struct pci_module_info;
struct pci_x86_module_info;
class OHCIRootHub; class OHCIRootHub;
typedef struct transfer_data { typedef struct transfer_data {
@@ -140,6 +141,8 @@ inline uint32 _ReadReg(uint32 reg);
ohci_general_td *topDescriptor); ohci_general_td *topDescriptor);
static pci_module_info * sPCIModule; static pci_module_info * sPCIModule;
static pci_x86_module_info * sPCIx86Module;
pci_info * fPCIInfo; pci_info * fPCIInfo;
Stack * fStack; Stack * fStack;