mirror of
https://review.haiku-os.org/haiku
synced 2025-01-31 18:56:49 +01:00
ohci: switch to the new driver API
Change-Id: I065743b5ced8b75f9576b62421525824698a2245 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5710 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
15ebede292
commit
0ed2fb8d75
@ -68,7 +68,6 @@ Stack::Stack()
|
||||
// ports before the EHCI module discovers them.
|
||||
const char *moduleNames[] = {
|
||||
"busses/usb/uhci",
|
||||
"busses/usb/ohci",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -9,50 +9,268 @@
|
||||
* Siarzhuk Zharski <imker@gmx.li>
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <module.h>
|
||||
#include <PCI.h>
|
||||
#include <PCI_x86.h>
|
||||
#include <bus/PCI.h>
|
||||
#include <USB3.h>
|
||||
#include <KernelExport.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include "ohci.h"
|
||||
|
||||
|
||||
#define CALLED(x...) TRACE_MODULE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
|
||||
#define USB_MODULE_NAME "ohci"
|
||||
|
||||
pci_module_info *OHCI::sPCIModule = NULL;
|
||||
pci_x86_module_info *OHCI::sPCIx86Module = NULL;
|
||||
static pci_x86_module_info* sPCIx86Module = NULL;
|
||||
static device_manager_info* gDeviceManager;
|
||||
static usb_for_controller_interface* gUSB;
|
||||
|
||||
|
||||
static int32
|
||||
ohci_std_ops(int32 op, ...)
|
||||
#define OHCI_PCI_DEVICE_MODULE_NAME "busses/usb/ohci/pci/driver_v1"
|
||||
#define OHCI_PCI_USB_BUS_MODULE_NAME "busses/usb/ohci/device_v1"
|
||||
|
||||
|
||||
typedef struct {
|
||||
OHCI* ohci;
|
||||
pci_device_module_info* pci;
|
||||
pci_device* device;
|
||||
|
||||
pci_info pciinfo;
|
||||
|
||||
device_node* node;
|
||||
device_node* driver_node;
|
||||
} ohci_pci_sim_info;
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
static status_t
|
||||
init_bus(device_node* node, void** bus_cookie)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
TRACE_MODULE("init module\n");
|
||||
return B_OK;
|
||||
case B_MODULE_UNINIT:
|
||||
TRACE_MODULE("uninit module\n");
|
||||
return B_OK;
|
||||
CALLED();
|
||||
|
||||
driver_module_info* driver;
|
||||
ohci_pci_sim_info* bus;
|
||||
device_node* parent = gDeviceManager->get_parent_node(node);
|
||||
gDeviceManager->get_driver(parent, &driver, (void**)&bus);
|
||||
gDeviceManager->put_node(parent);
|
||||
|
||||
Stack *stack;
|
||||
if (gUSB->get_stack((void**)&stack) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
OHCI *ohci = new(std::nothrow) OHCI(&bus->pciinfo, bus->pci, bus->device, stack);
|
||||
if (ohci == NULL) {
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
if (ohci->InitCheck() < B_OK) {
|
||||
TRACE_MODULE_ERROR("bus failed init check\n");
|
||||
delete ohci;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (ohci->Start() != B_OK) {
|
||||
delete ohci;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
*bus_cookie = ohci;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
usb_host_controller_info ohci_module = {
|
||||
static void
|
||||
uninit_bus(void* bus_cookie)
|
||||
{
|
||||
CALLED();
|
||||
OHCI* ohci = (OHCI*)bus_cookie;
|
||||
delete ohci;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
register_child_devices(void* cookie)
|
||||
{
|
||||
CALLED();
|
||||
ohci_pci_sim_info* bus = (ohci_pci_sim_info*)cookie;
|
||||
device_node* node = bus->driver_node;
|
||||
|
||||
char prettyName[25];
|
||||
sprintf(prettyName, "OHCI Controller %" B_PRIu16, 0);
|
||||
|
||||
device_attr attrs[] = {
|
||||
// properties of this controller for the usb bus manager
|
||||
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
|
||||
{ string: prettyName }},
|
||||
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
|
||||
{ string: USB_FOR_CONTROLLER_MODULE_NAME }},
|
||||
|
||||
// private data to identify the device
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
return gDeviceManager->register_node(node, OHCI_PCI_USB_BUS_MODULE_NAME,
|
||||
attrs, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_device(device_node* node, void** device_cookie)
|
||||
{
|
||||
CALLED();
|
||||
ohci_pci_sim_info* bus = (ohci_pci_sim_info*)calloc(1,
|
||||
sizeof(ohci_pci_sim_info));
|
||||
if (bus == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
pci_device_module_info* pci;
|
||||
pci_device* device;
|
||||
{
|
||||
"busses/usb/ohci",
|
||||
0,
|
||||
ohci_std_ops
|
||||
},
|
||||
NULL,
|
||||
OHCI::AddTo
|
||||
device_node* pciParent = gDeviceManager->get_parent_node(node);
|
||||
gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
|
||||
(void**)&device);
|
||||
gDeviceManager->put_node(pciParent);
|
||||
}
|
||||
|
||||
bus->pci = pci;
|
||||
bus->device = device;
|
||||
bus->driver_node = node;
|
||||
|
||||
pci_info *pciInfo = &bus->pciinfo;
|
||||
pci->get_pci_info(device, pciInfo);
|
||||
|
||||
if (sPCIx86Module == NULL) {
|
||||
dprintf("ohci_init_device get_module B_PCI_X86_MODULE_NAME\n");
|
||||
if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module) != B_OK)
|
||||
sPCIx86Module = NULL;
|
||||
}
|
||||
|
||||
*device_cookie = bus;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_device(void* device_cookie)
|
||||
{
|
||||
CALLED();
|
||||
ohci_pci_sim_info* bus = (ohci_pci_sim_info*)device_cookie;
|
||||
free(bus);
|
||||
|
||||
if (sPCIx86Module != NULL) {
|
||||
dprintf("ohci_uninit_device put_module B_PCI_X86_MODULE_NAME\n");
|
||||
put_module(B_PCI_X86_MODULE_NAME);
|
||||
sPCIx86Module = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
register_device(device_node* parent)
|
||||
{
|
||||
CALLED();
|
||||
device_attr attrs[] = {
|
||||
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "OHCI PCI"}},
|
||||
{}
|
||||
};
|
||||
|
||||
return gDeviceManager->register_node(parent,
|
||||
OHCI_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static float
|
||||
supports_device(device_node* parent)
|
||||
{
|
||||
CALLED();
|
||||
const char* bus;
|
||||
uint16 type, subType, api;
|
||||
|
||||
// make sure parent is a OHCI PCI device node
|
||||
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
|
||||
< B_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(bus, "pci") != 0)
|
||||
return 0.0f;
|
||||
|
||||
if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subType,
|
||||
false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type,
|
||||
false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_INTERFACE, &api,
|
||||
false) < B_OK) {
|
||||
TRACE_MODULE("Could not find type/subtype/interface attributes\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type == PCI_serial_bus && subType == PCI_usb && api == PCI_usb_ohci) {
|
||||
pci_device_module_info* pci;
|
||||
pci_device* device;
|
||||
gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
|
||||
(void**)&device);
|
||||
TRACE_MODULE("OHCI Device found!\n");
|
||||
|
||||
return 0.8f;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ USB_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gUSB },
|
||||
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&ohci_module,
|
||||
static usb_bus_interface gOHCIPCIDeviceModule = {
|
||||
{
|
||||
{
|
||||
OHCI_PCI_USB_BUS_MODULE_NAME,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
NULL, // supports device
|
||||
NULL, // register device
|
||||
init_bus,
|
||||
uninit_bus,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
NULL, // device removed
|
||||
},
|
||||
};
|
||||
|
||||
// Root device that binds to the PCI bus. It will register an usb_bus_interface
|
||||
// node for each device.
|
||||
static driver_module_info sOHCIDevice = {
|
||||
{
|
||||
OHCI_PCI_DEVICE_MODULE_NAME,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
supports_device,
|
||||
register_device,
|
||||
init_device,
|
||||
uninit_device,
|
||||
register_child_devices,
|
||||
NULL, // rescan
|
||||
NULL, // device removed
|
||||
};
|
||||
|
||||
module_info* modules[] = {
|
||||
(module_info* )&sOHCIDevice,
|
||||
(module_info* )&gOHCIPCIDeviceModule,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -62,88 +280,11 @@ module_info *modules[] = {
|
||||
//
|
||||
|
||||
|
||||
status_t
|
||||
OHCI::AddTo(Stack *stack)
|
||||
{
|
||||
if (!sPCIModule) {
|
||||
status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
|
||||
if (status < B_OK) {
|
||||
TRACE_MODULE_ERROR("getting pci module failed! 0x%08" B_PRIx32 "\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_MODULE("searching devices\n");
|
||||
bool found = false;
|
||||
pci_info *item = new(std::nothrow) pci_info;
|
||||
if (!item) {
|
||||
sPCIModule = NULL;
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
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++) {
|
||||
if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
|
||||
&& item->class_api == PCI_usb_ohci) {
|
||||
TRACE_MODULE("found device at PCI:%d:%d:%d\n",
|
||||
item->bus, item->device, item->function);
|
||||
OHCI *bus = new(std::nothrow) OHCI(item, stack);
|
||||
if (bus == NULL) {
|
||||
delete item;
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
if (sPCIx86Module != NULL)
|
||||
put_module(B_PCI_X86_MODULE_NAME);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// The bus will put the PCI modules when it is destroyed, so get
|
||||
// them again to increase their reference count.
|
||||
get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
|
||||
if (sPCIx86Module != NULL)
|
||||
get_module(B_PCI_X86_MODULE_NAME, (module_info **)&sPCIx86Module);
|
||||
|
||||
if (bus->InitCheck() < B_OK) {
|
||||
TRACE_MODULE_ERROR("bus failed init check\n");
|
||||
delete bus;
|
||||
continue;
|
||||
}
|
||||
|
||||
// the bus took it away
|
||||
item = new(std::nothrow) pci_info;
|
||||
|
||||
if (bus->Start() != B_OK) {
|
||||
delete bus;
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The modules will have been gotten again if we successfully
|
||||
// initialized a bus, so we should put them here.
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
if (sPCIx86Module != NULL)
|
||||
put_module(B_PCI_X86_MODULE_NAME);
|
||||
|
||||
if (!found)
|
||||
TRACE_MODULE_ERROR("no devices found\n");
|
||||
delete item;
|
||||
return found ? B_OK : ENODEV;
|
||||
}
|
||||
|
||||
|
||||
OHCI::OHCI(pci_info *info, Stack *stack)
|
||||
OHCI::OHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stack *stack)
|
||||
: BusManager(stack),
|
||||
fPCIInfo(info),
|
||||
fPci(pci),
|
||||
fDevice(device),
|
||||
fStack(stack),
|
||||
fOperationalRegisters(NULL),
|
||||
fRegisterArea(-1),
|
||||
@ -177,17 +318,14 @@ OHCI::OHCI(pci_info *info, Stack *stack)
|
||||
mutex_init(&fEndpointLock, "ohci endpoint lock");
|
||||
|
||||
// enable busmaster and memory mapped access
|
||||
uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
|
||||
uint16 command = fPci->read_pci_config(fDevice, PCI_command, 2);
|
||||
command &= ~PCI_command_io;
|
||||
command |= PCI_command_master | PCI_command_memory;
|
||||
|
||||
sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
|
||||
fPCIInfo->function, PCI_command, 2, command);
|
||||
fPci->write_pci_config(fDevice, PCI_command, 2, command);
|
||||
|
||||
// map the registers
|
||||
uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||
fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
|
||||
uint32 offset = fPci->read_pci_config(fDevice, PCI_base_registers, 4);
|
||||
offset &= PCI_address_memory_32_mask;
|
||||
TRACE_ALWAYS("iospace offset: 0x%" B_PRIx32 "\n", offset);
|
||||
fRegisterArea = map_physical_memory("OHCI memory mapped registers",
|
||||
|
@ -16,8 +16,8 @@
|
||||
#include <lock.h>
|
||||
|
||||
struct pci_info;
|
||||
struct pci_module_info;
|
||||
struct pci_x86_module_info;
|
||||
struct pci_device_module_info;
|
||||
struct pci_device;
|
||||
class OHCIRootHub;
|
||||
|
||||
typedef struct transfer_data {
|
||||
@ -34,9 +34,7 @@ typedef struct transfer_data {
|
||||
|
||||
class OHCI : public BusManager {
|
||||
public:
|
||||
static status_t AddTo(Stack *stack);
|
||||
|
||||
OHCI(pci_info *info, Stack *stack);
|
||||
OHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stack *stack);
|
||||
~OHCI();
|
||||
|
||||
status_t Start();
|
||||
@ -181,10 +179,9 @@ inline uint32 _ReadReg(uint32 reg);
|
||||
void _PrintDescriptorChain(
|
||||
ohci_isochronous_td *topDescriptor);
|
||||
|
||||
static pci_module_info * sPCIModule;
|
||||
static pci_x86_module_info * sPCIx86Module;
|
||||
|
||||
pci_info * fPCIInfo;
|
||||
pci_device_module_info* fPci;
|
||||
pci_device* fDevice;
|
||||
Stack * fStack;
|
||||
|
||||
uint8 * fOperationalRegisters;
|
||||
|
Loading…
x
Reference in New Issue
Block a user