Add functions to the old-style PCI bus manager to reserve a device from an old-style driver for exclusive use. This should help making OSS and native audio drivers mutually exclusive. Used in es1370 and hda drivers as examples. OSS must still be fixed to use it too though.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32899 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2009-09-01 23:56:02 +00:00
parent 271b9ad49a
commit 7e26ad5af7
6 changed files with 251 additions and 4 deletions

View File

@ -155,6 +155,18 @@ struct pci_module_info {
uchar cap_id,
uchar *offset
);
status_t (*reserve_device) (
uchar bus,
uchar device,
uchar function,
const char *driver_name,
void *cookie);
status_t (*unreserve_device) (
uchar bus,
uchar device,
uchar function,
const char *driver_name,
void *cookie);
};
#define B_PCI_MODULE_NAME "bus_managers/pci/v1"

View File

@ -86,6 +86,196 @@ pci_find_capability(uchar virtualBus, uchar device, uchar function,
}
status_t
pci_reserve_device(uchar virtualBus, uchar device, uchar function,
const char *driverName, void *nodeCookie)
{
status_t status;
uint8 bus;
int domain;
/*
* we add 2 nodes to the PCI devices, one with constant attributes,
* so adding for another driver fails, and a subnode with the
* driver-provided informations.
*/
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
return B_ERROR;
//TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
// domain, bus, device, function, driverName, nodeCookie));
device_attr matchPCIRoot[] = {
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}},
{NULL}
};
device_attr matchThis[] = {
// info about device
{B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}},
// location on PCI bus
{B_PCI_DEVICE_DOMAIN, B_UINT32_TYPE, {ui32: domain}},
{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}},
{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: device}},
{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: function}},
{NULL}
};
device_attr legacyAttrs[] = {
// info about device
{B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}},
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Legacy Driver Reservation"}},
{NULL}
};
device_attr drvAttrs[] = {
// info about device
{B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}},
{"legacy_driver", B_STRING_TYPE, {string: driverName}},
{"legacy_driver_cookie", B_UINT64_TYPE, {ui64: (uint64)nodeCookie}},
{NULL}
};
device_node *root, *pci, *node, *legacy;
status = B_DEVICE_NOT_FOUND;
root = gDeviceManager->get_root_node();
if (!root)
return status;
pci = NULL;
if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK)
goto err0;
node = NULL;
if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK)
goto err1;
// common API for all legacy modules ?
//status = legacy_driver_register(node, driverName, nodeCookie, PCI_LEGACY_DRIVER_MODULE_NAME);
status = gDeviceManager->register_node(node, PCI_LEGACY_DRIVER_MODULE_NAME,
legacyAttrs, NULL, &legacy);
if (status < B_OK)
goto err2;
status = gDeviceManager->register_node(legacy, PCI_LEGACY_DRIVER_MODULE_NAME,
drvAttrs, NULL, NULL);
if (status < B_OK)
goto err3;
gDeviceManager->put_node(node);
gDeviceManager->put_node(pci);
gDeviceManager->put_node(root);
return B_OK;
err3:
gDeviceManager->unregister_node(legacy);
err2:
gDeviceManager->put_node(node);
err1:
gDeviceManager->put_node(pci);
err0:
gDeviceManager->put_node(root);
TRACE(("pci_reserve_device for driver %s failed: %s\n", driverName, strerror(status)));
return status;
}
status_t
pci_unreserve_device(uchar virtualBus, uchar device, uchar function,
const char *driverName, void *nodeCookie)
{
status_t status;
uint8 bus;
int domain;
if (gPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK)
return B_ERROR;
//TRACE(("%s(%d [%d:%d], %d, %d, %s, %p)\n", __FUNCTION__, virtualBus,
// domain, bus, device, function, driverName, nodeCookie));
device_attr matchPCIRoot[] = {
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}},
{NULL}
};
device_attr matchThis[] = {
// info about device
{B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}},
// location on PCI bus
{B_PCI_DEVICE_DOMAIN, B_UINT32_TYPE, {ui32: domain}},
{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}},
{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: device}},
{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: function}},
{NULL}
};
device_attr legacyAttrs[] = {
// info about device
{B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}},
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Legacy Driver Reservation"}},
{NULL}
};
device_attr drvAttrs[] = {
// info about device
{B_DEVICE_BUS, B_STRING_TYPE, {string: "legacy_driver"}},
{"legacy_driver", B_STRING_TYPE, {string: driverName}},
{"legacy_driver_cookie", B_UINT64_TYPE, {ui64: (uint64)nodeCookie}},
{NULL}
};
device_node *root, *pci, *node, *legacy, *drv;
status = B_DEVICE_NOT_FOUND;
root = gDeviceManager->get_root_node();
if (!root)
return status;
pci = NULL;
if (gDeviceManager->get_next_child_node(root, matchPCIRoot, &pci) < B_OK)
goto err0;
node = NULL;
if (gDeviceManager->get_next_child_node(pci, matchThis, &node) < B_OK)
goto err1;
// common API for all legacy modules ?
//status = legacy_driver_unregister(node, driverName, nodeCookie);
legacy = NULL;
if (gDeviceManager->get_next_child_node(node, legacyAttrs, &legacy) < B_OK)
goto err2;
drv = NULL;
if (gDeviceManager->get_next_child_node(legacy, drvAttrs, &drv) < B_OK)
goto err3;
gDeviceManager->put_node(drv);
status = gDeviceManager->unregister_node(drv);
//dprintf("unreg:drv:%s\n", strerror(status));
gDeviceManager->put_node(legacy);
status = gDeviceManager->unregister_node(legacy);
//dprintf("unreg:legacy:%s\n", strerror(status));
// we'll get EBUSY here anyway...
gDeviceManager->put_node(node);
gDeviceManager->put_node(pci);
gDeviceManager->put_node(root);
return B_OK;
err3:
gDeviceManager->put_node(legacy);
err2:
gDeviceManager->put_node(node);
err1:
gDeviceManager->put_node(pci);
err0:
gDeviceManager->put_node(root);
TRACE(("pci_unreserve_device for driver %s failed: %s\n", driverName, strerror(status)));
return status;
}
// used by pci_info.cpp print_info_basic()
void
__pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus)

View File

@ -64,7 +64,9 @@ static struct pci_module_info sOldPCIModule = {
&pci_read_config,
&pci_write_config,
&pci_ram_address,
&pci_find_capability
&pci_find_capability,
&pci_reserve_device,
&pci_unreserve_device
};
module_dependency module_dependencies[] = {
@ -72,9 +74,19 @@ module_dependency module_dependencies[] = {
{}
};
driver_module_info gPCILegacyDriverModule = {
{
PCI_LEGACY_DRIVER_MODULE_NAME,
0,
NULL,
},
NULL
};
module_info *modules[] = {
(module_info *)&sOldPCIModule,
(module_info *)&gPCIRootModule,
(module_info *)&gPCIDeviceModule,
(module_info *)&gPCILegacyDriverModule,
NULL
};

View File

@ -12,6 +12,8 @@
#include <device_manager.h>
#include <bus/PCI.h>
// name of PCI legacy driver endpoint module
#define PCI_LEGACY_DRIVER_MODULE_NAME "bus_managers/pci/legacy_v1"
// name of PCI device modules
#define PCI_DEVICE_MODULE_NAME "bus_managers/pci/driver_v1"
@ -46,6 +48,11 @@ void * pci_ram_address(const void *physical_address_in_system_memory);
status_t pci_find_capability(uchar bus, uchar device, uchar function, uchar cap_id, uchar *offset);
status_t pci_reserve_device(uchar virtualBus, uchar device, uchar function,
const char *driverName, void *nodeCookie);
status_t pci_unreserve_device(uchar virtualBus, uchar device, uchar function,
const char *driverName, void *nodeCookie);
status_t pci_io_init(void);
uint8 pci_read_io_8(int mapped_io_addr);
void pci_write_io_8(int mapped_io_addr, uint8 value);

View File

@ -501,6 +501,7 @@ init_driver(void)
pci_info info;
int ix = 0;
num_cards = 0;
status_t err;
PRINT(("init_driver()\n"));
@ -529,7 +530,7 @@ init_driver(void)
if (get_module(pci_name, (module_info **) &pci))
return ENOSYS;
while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) {
if (info.vendor_id == 0x1274
&& (info.device_id == 0x5000
/*|| info.device_id == 0x1371
@ -541,6 +542,14 @@ init_driver(void)
}
memset(&cards[num_cards], 0, sizeof(es1370_dev));
cards[num_cards].info = info;
#ifdef __HAIKU__
if ((err = (*pci->reserve_device)(info.bus, info.device, info.function,
DRIVER_NAME, &cards[num_cards])) < B_OK) {
dprintf("es1370: failed to reserve_device(%d, %d, %d,): %s\n",
info.bus, info.device, info.function, strerror(err));
continue;
}
#endif
if (es1370_setup(&cards[num_cards])) {
PRINT(("Setup of es1370 %ld failed\n", num_cards+1));
}
@ -548,7 +557,6 @@ init_driver(void)
num_cards++;
}
}
ix++;
}
if (!num_cards) {
PRINT(("no cards\n"));
@ -579,8 +587,14 @@ uninit_driver(void)
num_cards = 0;
PRINT(("uninit_driver()\n"));
for (ix=0; ix<cnt; ix++)
for (ix=0; ix<cnt; ix++) {
es1370_shutdown(&cards[ix]);
#ifdef __HAIKU__
(*pci->unreserve_device)(cards[ix].info.bus,
cards[ix].info.device, cards[ix].info.function,
DRIVER_NAME, &cards[ix]);
#endif
}
memset(&cards, 0, sizeof(cards));
put_module(pci_name);
}

View File

@ -55,6 +55,14 @@ init_driver(void)
&& gNumCards < MAX_CARDS; i++) {
if (info.class_base == PCI_multimedia
&& info.class_sub == PCI_hd_audio) {
#ifdef __HAIKU__
if ((*gPci->reserve_device)(info.bus, info.device, info.function, "hda",
&gCards[gNumCards]) < B_OK) {
dprintf("HDA: Failed to reserve PCI:%d:%d:%d\n",
info.bus, info.device, info.function);
continue;
}
#endif
memset(&gCards[gNumCards], 0, sizeof(hda_controller));
gCards[gNumCards].pci_info = info;
gCards[gNumCards].opened = 0;
@ -84,6 +92,10 @@ uninit_driver(void)
dprintf("IRA: %s\n", __func__);
for (uint32 i = 0; i < gNumCards; i++) {
#ifdef __HAIKU__
(*gPci->unreserve_device)(gCards[i].pci_info.bus, gCards[i].pci_info.device,
gCards[i].pci_info.function, "hda", &gCards[i]);
#endif
free((void*)gCards[i].devfs_path);
gCards[i].devfs_path = NULL;
}