* Copyright 2018-2021 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* B Krishnan Iyer, krishnaniyer97@gmail.com
* Adrien Destugues, pulkomandy@pulkomandy.tk
*/
#include "mmc_bus.h"
#define MMC_BUS_DEVICE_NAME "bus_managers/mmc_bus/device/v1"
device_manager_info* gDeviceManager = NULL;
static status_t
mmc_bus_init(device_node* node, void** _device)
{
CALLED();
MMCBus* device = new(std::nothrow) MMCBus(node);
if (device == NULL) {
ERROR("Unable to allocate MMC bus\n");
return B_NO_MEMORY;
}
status_t result = device->InitCheck();
if (result != B_OK) {
TRACE("failed to set up mmc bus device object\n");
return result;
}
TRACE("MMC bus object created\n");
*_device = device;
return B_OK;
}
static void
mmc_bus_uninit(void* _device)
{
CALLED();
MMCBus* device = (MMCBus*)_device;
delete device;
}
static status_t
mmc_bus_register_child(void* _device)
{
return B_OK;
}
static void
mmc_bus_removed(void* _device)
{
CALLED();
}
status_t
mmc_bus_added_device(device_node* parent)
{
CALLED();
device_attr attributes[] = {
{ B_DEVICE_BUS, B_STRING_TYPE, { .string = "mmc"}},
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "MMC bus root"}},
{ NULL }
};
return gDeviceManager->register_node(parent, MMC_BUS_DEVICE_NAME,
attributes, NULL, NULL);
}
static status_t
mmc_bus_execute_command(device_node* node, void* cookie, uint16_t rca,
uint8_t command, uint32_t argument, uint32_t* result)
{
TRACE("In mmc_bus_execute_command\n");
MMCBus* bus = (MMCBus*)cookie;
bus->AcquireBus();
status_t error = bus->ExecuteCommand(rca, command, argument, result);
bus->ReleaseBus();
return error;
}
static status_t
mmc_bus_do_io(device_node* node, void* cookie, uint16_t rca, uint8_t command,
IOOperation* operation, bool offsetAsSectors)
{
MMCBus* bus = (MMCBus*)cookie;
status_t result = B_OK;
bus->AcquireBus();
result = bus->DoIO(rca, command, operation, offsetAsSectors);
bus->ReleaseBus();
return result;
}
static void
mmc_bus_set_width(device_node* node, void* cookie, int width)
{
MMCBus* bus = (MMCBus*)cookie;
bus->AcquireBus();
bus->SetBusWidth(width);
bus->ReleaseBus();
}
static status_t
std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
default:
break;
}
return B_ERROR;
}
driver_module_info mmc_bus_device_module = {
{
MMC_BUS_DEVICE_NAME,
0,
std_ops
},
NULL,
NULL,
mmc_bus_init,
mmc_bus_uninit,
mmc_bus_register_child,
NULL,
mmc_bus_removed,
NULL,
NULL
};
mmc_device_interface mmc_bus_controller_module = {
{
{
MMC_BUS_MODULE_NAME,
0,
&std_ops
},
NULL,
mmc_bus_added_device,
NULL,
NULL,
NULL
},
mmc_bus_execute_command,
mmc_bus_do_io,
mmc_bus_set_width
};
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
{}
};
module_info* modules[] = {
(module_info*)&mmc_bus_controller_module,
(module_info*)&mmc_bus_device_module,
NULL
};