hdaudio: enable MSI support
* disabled for nVidia and Creative Technology devices.
This commit is contained in:
@@ -15,6 +15,7 @@ int32 api_version = B_CUR_DRIVER_API_VERSION;
|
|||||||
hda_controller gCards[MAX_CARDS];
|
hda_controller gCards[MAX_CARDS];
|
||||||
uint32 gNumCards;
|
uint32 gNumCards;
|
||||||
pci_module_info* gPci;
|
pci_module_info* gPci;
|
||||||
|
pci_x86_module_info* gPCIx86Module;
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
@@ -82,6 +83,10 @@ init_driver(void)
|
|||||||
return ENODEV;
|
return ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&gPCIx86Module)
|
||||||
|
!= B_OK)
|
||||||
|
gPCIx86Module = NULL;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,8 +104,12 @@ uninit_driver(void)
|
|||||||
free((void*)gCards[i].devfs_path);
|
free((void*)gCards[i].devfs_path);
|
||||||
gCards[i].devfs_path = NULL;
|
gCards[i].devfs_path = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
put_module(B_PCI_MODULE_NAME);
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
if (gPCIx86Module != NULL) {
|
||||||
|
put_module(B_PCI_X86_MODULE_NAME);
|
||||||
|
gPCIx86Module = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <Drivers.h>
|
#include <Drivers.h>
|
||||||
#include <PCI.h>
|
#include <PCI.h>
|
||||||
|
#include <PCI_x86.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -334,6 +335,7 @@ struct hda_multi {
|
|||||||
/* driver.c */
|
/* driver.c */
|
||||||
extern device_hooks gDriverHooks;
|
extern device_hooks gDriverHooks;
|
||||||
extern pci_module_info* gPci;
|
extern pci_module_info* gPci;
|
||||||
|
extern pci_x86_module_info* gPCIx86Module;
|
||||||
extern hda_controller gCards[MAX_CARDS];
|
extern hda_controller gCards[MAX_CARDS];
|
||||||
extern uint32 gNumCards;
|
extern uint32 gNumCards;
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <PCI_x86.h>
|
|
||||||
|
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "hda_codec_defs.h"
|
#include "hda_codec_defs.h"
|
||||||
|
|
||||||
@@ -36,10 +34,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#define PCI_VENDOR_AMD 0x1002
|
#define PCI_VENDOR_AMD 0x1002
|
||||||
|
#define PCI_VENDOR_CREATIVE 0x1102
|
||||||
#define PCI_VENDOR_INTEL 0x8086
|
#define PCI_VENDOR_INTEL 0x8086
|
||||||
#define PCI_VENDOR_NVIDIA 0x10de
|
#define PCI_VENDOR_NVIDIA 0x10de
|
||||||
#define PCI_ALL_DEVICES 0xffffffff
|
#define PCI_ALL_DEVICES 0xffffffff
|
||||||
#define HDA_QUIRK_SNOOP 0x0001
|
#define HDA_QUIRK_SNOOP 0x0001
|
||||||
|
#define HDA_QUIRK_NO_MSI 0x0002
|
||||||
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -58,7 +58,9 @@ static const struct {
|
|||||||
// Enable snooping for ATI and Nvidia, right now for all their hda-devices,
|
// Enable snooping for ATI and Nvidia, right now for all their hda-devices,
|
||||||
// but only based on guessing.
|
// but only based on guessing.
|
||||||
{ PCI_VENDOR_AMD, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP },
|
{ PCI_VENDOR_AMD, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP },
|
||||||
{ PCI_VENDOR_NVIDIA, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP },
|
{ PCI_VENDOR_NVIDIA, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP | HDA_QUIRK_NO_MSI },
|
||||||
|
{ PCI_VENDOR_CREATIVE, 0x0010, HDA_QUIRK_NO_MSI },
|
||||||
|
{ PCI_VENDOR_CREATIVE, 0x0012, HDA_QUIRK_NO_MSI }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -83,9 +85,6 @@ static const struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static pci_x86_module_info* sPCIx86Module;
|
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
get_controller_quirks(pci_info& info)
|
get_controller_quirks(pci_info& info)
|
||||||
{
|
{
|
||||||
@@ -853,7 +852,7 @@ hda_hw_init(hda_controller* controller)
|
|||||||
uint16 stateStatus;
|
uint16 stateStatus;
|
||||||
uint16 cmd;
|
uint16 cmd;
|
||||||
status_t status;
|
status_t status;
|
||||||
uint32 quirks;
|
uint32 quirks = get_controller_quirks(controller->pci_info);
|
||||||
|
|
||||||
// Map MMIO registers
|
// Map MMIO registers
|
||||||
controller->regs_area = map_physical_memory("hda_hw_regs",
|
controller->regs_area = map_physical_memory("hda_hw_regs",
|
||||||
@@ -884,27 +883,21 @@ hda_hw_init(hda_controller* controller)
|
|||||||
controller->pci_info.device, controller->pci_info.function,
|
controller->pci_info.device, controller->pci_info.function,
|
||||||
PCI_command, 2, cmd);
|
PCI_command, 2, cmd);
|
||||||
|
|
||||||
if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module)
|
|
||||||
!= B_OK)
|
|
||||||
sPCIx86Module = NULL;
|
|
||||||
|
|
||||||
// Absolute minimum hw is online; we can now install interrupt handler
|
// Absolute minimum hw is online; we can now install interrupt handler
|
||||||
|
|
||||||
controller->irq = controller->pci_info.u.h0.interrupt_line;
|
controller->irq = controller->pci_info.u.h0.interrupt_line;
|
||||||
controller->msi = false;
|
controller->msi = false;
|
||||||
|
|
||||||
// TODO: temporarily disabled, as at least on my hardware audio becomes
|
if (gPCIx86Module != NULL && (quirks & HDA_QUIRK_NO_MSI) == 0
|
||||||
// flaky after this.
|
&& gPCIx86Module->get_msi_count(
|
||||||
/*
|
controller->pci_info.bus, controller->pci_info.device,
|
||||||
if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(
|
controller->pci_info.function) >= 1) {
|
||||||
controller->pci_info.bus, controller->pci_info.device,
|
|
||||||
controller->pci_info.function) >= 1) {
|
|
||||||
// Try MSI first
|
// Try MSI first
|
||||||
uint8 vector;
|
uint8 vector;
|
||||||
if (sPCIx86Module->configure_msi(controller->pci_info.bus,
|
if (gPCIx86Module->configure_msi(controller->pci_info.bus,
|
||||||
controller->pci_info.device, controller->pci_info.function,
|
controller->pci_info.device, controller->pci_info.function,
|
||||||
1, &vector) == B_OK
|
1, &vector) == B_OK
|
||||||
&& sPCIx86Module->enable_msi(controller->pci_info.bus,
|
&& gPCIx86Module->enable_msi(controller->pci_info.bus,
|
||||||
controller->pci_info.device, controller->pci_info.function)
|
controller->pci_info.device, controller->pci_info.function)
|
||||||
== B_OK) {
|
== B_OK) {
|
||||||
dprintf("hda: using MSI vector %u\n", vector);
|
dprintf("hda: using MSI vector %u\n", vector);
|
||||||
@@ -912,7 +905,6 @@ hda_hw_init(hda_controller* controller)
|
|||||||
controller->msi = true;
|
controller->msi = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
status = install_io_interrupt_handler(controller->irq,
|
status = install_io_interrupt_handler(controller->irq,
|
||||||
(interrupt_handler)hda_interrupt_handler, controller, 0);
|
(interrupt_handler)hda_interrupt_handler, controller, 0);
|
||||||
@@ -922,7 +914,6 @@ hda_hw_init(hda_controller* controller)
|
|||||||
// TCSEL is reset to TC0 (clear 0-2 bits)
|
// TCSEL is reset to TC0 (clear 0-2 bits)
|
||||||
update_pci_register(controller, PCI_HDA_TCSEL, PCI_HDA_TCSEL_MASK, 0, 1);
|
update_pci_register(controller, PCI_HDA_TCSEL, PCI_HDA_TCSEL_MASK, 0, 1);
|
||||||
|
|
||||||
quirks = get_controller_quirks(controller->pci_info);
|
|
||||||
if ((quirks & HDA_QUIRK_SNOOP) != 0) {
|
if ((quirks & HDA_QUIRK_SNOOP) != 0) {
|
||||||
switch (controller->pci_info.vendor_id) {
|
switch (controller->pci_info.vendor_id) {
|
||||||
case PCI_VENDOR_NVIDIA:
|
case PCI_VENDOR_NVIDIA:
|
||||||
@@ -1025,7 +1016,7 @@ corb_rirb_failed:
|
|||||||
|
|
||||||
reset_failed:
|
reset_failed:
|
||||||
if (controller->msi) {
|
if (controller->msi) {
|
||||||
sPCIx86Module->disable_msi(controller->pci_info.bus,
|
gPCIx86Module->disable_msi(controller->pci_info.bus,
|
||||||
controller->pci_info.device, controller->pci_info.function);
|
controller->pci_info.device, controller->pci_info.function);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1037,11 +1028,6 @@ no_irq:
|
|||||||
controller->regs_area = B_ERROR;
|
controller->regs_area = B_ERROR;
|
||||||
controller->regs = NULL;
|
controller->regs = NULL;
|
||||||
|
|
||||||
if (sPCIx86Module != NULL) {
|
|
||||||
put_module(B_PCI_X86_MODULE_NAME);
|
|
||||||
sPCIx86Module = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
dprintf("hda: ERROR: %s(%ld)\n", strerror(status), status);
|
dprintf("hda: ERROR: %s(%ld)\n", strerror(status), status);
|
||||||
|
|
||||||
@@ -1083,16 +1069,16 @@ hda_hw_uninit(hda_controller* controller)
|
|||||||
|
|
||||||
if (controller->msi) {
|
if (controller->msi) {
|
||||||
// Disable MSI
|
// Disable MSI
|
||||||
sPCIx86Module->disable_msi(controller->pci_info.bus,
|
gPCIx86Module->disable_msi(controller->pci_info.bus,
|
||||||
controller->pci_info.device, controller->pci_info.function);
|
controller->pci_info.device, controller->pci_info.function);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_io_interrupt_handler(controller->irq,
|
remove_io_interrupt_handler(controller->irq,
|
||||||
(interrupt_handler)hda_interrupt_handler, controller);
|
(interrupt_handler)hda_interrupt_handler, controller);
|
||||||
|
|
||||||
if (sPCIx86Module != NULL) {
|
if (gPCIx86Module != NULL) {
|
||||||
put_module(B_PCI_X86_MODULE_NAME);
|
put_module(B_PCI_X86_MODULE_NAME);
|
||||||
sPCIx86Module = NULL;
|
gPCIx86Module = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete corb/rirb area
|
// Delete corb/rirb area
|
||||||
|
|||||||
Reference in New Issue
Block a user