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:
Jérôme Duval 2022-10-01 17:03:42 +02:00 committed by waddlesplash
parent 15ebede292
commit 0ed2fb8d75
3 changed files with 251 additions and 117 deletions

View File

@ -68,7 +68,6 @@ Stack::Stack()
// ports before the EHCI module discovers them.
const char *moduleNames[] = {
"busses/usb/uhci",
"busses/usb/ohci",
NULL
};

View File

@ -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",

View File

@ -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;