125b6a6f1Skrish_iyer /* 225b6a6f1Skrish_iyer * Copyright 2018 Haiku, Inc. All rights reserved. 325b6a6f1Skrish_iyer * Distributed under the terms of the MIT License. 425b6a6f1Skrish_iyer * 525b6a6f1Skrish_iyer * Authors: 625b6a6f1Skrish_iyer * B Krishnan Iyer, krishnaniyer97@gmail.com 725b6a6f1Skrish_iyer */ 825b6a6f1Skrish_iyer #include "mmc_bus.h" 925b6a6f1Skrish_iyer 1025b6a6f1Skrish_iyer 11ff76d2dfSAdrien Destugues #define MMC_BUS_DEVICE_NAME "bus_managers/mmc_bus/device/v1" 12ff76d2dfSAdrien Destugues 13ff76d2dfSAdrien Destugues 1425b6a6f1Skrish_iyer device_manager_info* gDeviceManager = NULL; 1525b6a6f1Skrish_iyer 1625b6a6f1Skrish_iyer 1725b6a6f1Skrish_iyer static status_t 1825b6a6f1Skrish_iyer mmc_bus_init(device_node* node, void** _device) 1925b6a6f1Skrish_iyer { 2025b6a6f1Skrish_iyer CALLED(); 2125b6a6f1Skrish_iyer MMCBus* device = new(std::nothrow) MMCBus(node); 2225b6a6f1Skrish_iyer if (device == NULL) { 2325b6a6f1Skrish_iyer ERROR("Unable to allocate MMC bus\n"); 2425b6a6f1Skrish_iyer return B_NO_MEMORY; 2525b6a6f1Skrish_iyer } 2625b6a6f1Skrish_iyer 2725b6a6f1Skrish_iyer status_t result = device->InitCheck(); 2825b6a6f1Skrish_iyer if (result != B_OK) { 2925b6a6f1Skrish_iyer TRACE("failed to set up mmc bus device object\n"); 3025b6a6f1Skrish_iyer return result; 3125b6a6f1Skrish_iyer } 3225b6a6f1Skrish_iyer TRACE("MMC bus object created\n"); 3325b6a6f1Skrish_iyer 3425b6a6f1Skrish_iyer *_device = device; 3525b6a6f1Skrish_iyer return B_OK; 3625b6a6f1Skrish_iyer } 3725b6a6f1Skrish_iyer 3825b6a6f1Skrish_iyer 3925b6a6f1Skrish_iyer static void 4025b6a6f1Skrish_iyer mmc_bus_uninit(void* _device) 4125b6a6f1Skrish_iyer { 4225b6a6f1Skrish_iyer CALLED(); 4325b6a6f1Skrish_iyer MMCBus* device = (MMCBus*)_device; 4425b6a6f1Skrish_iyer delete device; 4525b6a6f1Skrish_iyer } 4625b6a6f1Skrish_iyer 4725b6a6f1Skrish_iyer 48dedbe94eSAdrien Destugues static status_t 49dedbe94eSAdrien Destugues mmc_bus_register_child(void* _device) 50dedbe94eSAdrien Destugues { 51dedbe94eSAdrien Destugues CALLED(); 52dedbe94eSAdrien Destugues MMCBus* device = (MMCBus*)_device; 53dedbe94eSAdrien Destugues device->Rescan(); 54dedbe94eSAdrien Destugues return B_OK; 55dedbe94eSAdrien Destugues } 56dedbe94eSAdrien Destugues 57dedbe94eSAdrien Destugues 5825b6a6f1Skrish_iyer static void 5925b6a6f1Skrish_iyer mmc_bus_removed(void* _device) 6025b6a6f1Skrish_iyer { 6125b6a6f1Skrish_iyer CALLED(); 6225b6a6f1Skrish_iyer } 6325b6a6f1Skrish_iyer 6425b6a6f1Skrish_iyer 6525b6a6f1Skrish_iyer status_t 6625b6a6f1Skrish_iyer mmc_bus_added_device(device_node* parent) 6725b6a6f1Skrish_iyer { 6825b6a6f1Skrish_iyer CALLED(); 6925b6a6f1Skrish_iyer 7025b6a6f1Skrish_iyer device_attr attributes[] = { 71dedbe94eSAdrien Destugues { B_DEVICE_BUS, B_STRING_TYPE, { string: "mmc"}}, 72dedbe94eSAdrien Destugues { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "MMC bus root"}}, 7325b6a6f1Skrish_iyer { NULL } 7425b6a6f1Skrish_iyer }; 7525b6a6f1Skrish_iyer 76ff76d2dfSAdrien Destugues return gDeviceManager->register_node(parent, MMC_BUS_DEVICE_NAME, 7725b6a6f1Skrish_iyer attributes, NULL, NULL); 7825b6a6f1Skrish_iyer } 7925b6a6f1Skrish_iyer 8025b6a6f1Skrish_iyer 8125b6a6f1Skrish_iyer static status_t 8262eaf4c0SAdrien Destugues mmc_bus_execute_command(device_node* node, uint8_t command, uint32_t argument, 8362eaf4c0SAdrien Destugues uint32_t* result) 8462eaf4c0SAdrien Destugues { 85*74b60970SAnarchos // FIXME store the parent cookie in the bus cookie or something instead of 86*74b60970SAnarchos // getting/putting the parent each time. 87*74b60970SAnarchos driver_module_info* mmc; 8862eaf4c0SAdrien Destugues void* cookie; 8962eaf4c0SAdrien Destugues 9062eaf4c0SAdrien Destugues TRACE("In mmc_bus_execute_command\n"); 9162eaf4c0SAdrien Destugues device_node* parent = gDeviceManager->get_parent_node(node); 92*74b60970SAnarchos gDeviceManager->get_driver(parent, &mmc, &cookie); 9362eaf4c0SAdrien Destugues gDeviceManager->put_node(parent); 9462eaf4c0SAdrien Destugues 95*74b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 96*74b60970SAnarchos 97*74b60970SAnarchos bus->AcquireBus(); 98*74b60970SAnarchos status_t error = bus->ExecuteCommand(command, argument, result); 99*74b60970SAnarchos bus->ReleaseBus(); 100*74b60970SAnarchos return error; 101*74b60970SAnarchos } 102*74b60970SAnarchos 103*74b60970SAnarchos 104*74b60970SAnarchos static status_t 105*74b60970SAnarchos mmc_bus_read_naive(device_node* node, uint16_t rca, off_t pos, void* buffer, 106*74b60970SAnarchos size_t* _length) 107*74b60970SAnarchos { 108*74b60970SAnarchos // FIXME store the parent cookie in the bus cookie or something instead of 109*74b60970SAnarchos // getting/putting the parent each time. 110*74b60970SAnarchos driver_module_info* mmc; 111*74b60970SAnarchos void* cookie; 112*74b60970SAnarchos 113*74b60970SAnarchos device_node* parent = gDeviceManager->get_parent_node(node); 114*74b60970SAnarchos gDeviceManager->get_driver(parent, &mmc, &cookie); 115*74b60970SAnarchos gDeviceManager->put_node(parent); 116*74b60970SAnarchos 117*74b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 118*74b60970SAnarchos bus->AcquireBus(); 119*74b60970SAnarchos status_t result = bus->Read(rca, pos, buffer, _length); 120*74b60970SAnarchos bus->ReleaseBus(); 121*74b60970SAnarchos return result; 12262eaf4c0SAdrien Destugues } 12362eaf4c0SAdrien Destugues 12462eaf4c0SAdrien Destugues 12562eaf4c0SAdrien Destugues static status_t 12625b6a6f1Skrish_iyer std_ops(int32 op, ...) 12725b6a6f1Skrish_iyer { 12825b6a6f1Skrish_iyer switch (op) { 12925b6a6f1Skrish_iyer case B_MODULE_INIT: 13025b6a6f1Skrish_iyer // Nothing to do 13125b6a6f1Skrish_iyer case B_MODULE_UNINIT: 13225b6a6f1Skrish_iyer return B_OK; 13325b6a6f1Skrish_iyer 13425b6a6f1Skrish_iyer default: 13525b6a6f1Skrish_iyer break; 13625b6a6f1Skrish_iyer } 13725b6a6f1Skrish_iyer 13825b6a6f1Skrish_iyer return B_ERROR; 13925b6a6f1Skrish_iyer } 14025b6a6f1Skrish_iyer 14125b6a6f1Skrish_iyer 14225b6a6f1Skrish_iyer driver_module_info mmc_bus_device_module = { 14325b6a6f1Skrish_iyer { 144ff76d2dfSAdrien Destugues MMC_BUS_DEVICE_NAME, 14525b6a6f1Skrish_iyer 0, 14625b6a6f1Skrish_iyer std_ops 14725b6a6f1Skrish_iyer }, 14825b6a6f1Skrish_iyer NULL, // supported devices 14925b6a6f1Skrish_iyer NULL, // register node 15025b6a6f1Skrish_iyer mmc_bus_init, 15125b6a6f1Skrish_iyer mmc_bus_uninit, 152dedbe94eSAdrien Destugues mmc_bus_register_child, 15325b6a6f1Skrish_iyer NULL, // rescan 15425b6a6f1Skrish_iyer mmc_bus_removed, 15525b6a6f1Skrish_iyer NULL, // suspend 15625b6a6f1Skrish_iyer NULL // resume 15725b6a6f1Skrish_iyer }; 15825b6a6f1Skrish_iyer 15925b6a6f1Skrish_iyer 16062eaf4c0SAdrien Destugues mmc_device_interface mmc_bus_controller_module = { 16162eaf4c0SAdrien Destugues { 16225b6a6f1Skrish_iyer { 163ff76d2dfSAdrien Destugues MMC_BUS_MODULE_NAME, 16425b6a6f1Skrish_iyer 0, 16525b6a6f1Skrish_iyer &std_ops 16625b6a6f1Skrish_iyer }, 16725b6a6f1Skrish_iyer 16825b6a6f1Skrish_iyer NULL, // supported devices 16925b6a6f1Skrish_iyer mmc_bus_added_device, 17025b6a6f1Skrish_iyer NULL, 17125b6a6f1Skrish_iyer NULL, 17225b6a6f1Skrish_iyer NULL 17362eaf4c0SAdrien Destugues }, 174*74b60970SAnarchos mmc_bus_execute_command, 175*74b60970SAnarchos mmc_bus_read_naive 17625b6a6f1Skrish_iyer }; 17725b6a6f1Skrish_iyer 17825b6a6f1Skrish_iyer 17925b6a6f1Skrish_iyer module_dependency module_dependencies[] = { 18025b6a6f1Skrish_iyer { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 18125b6a6f1Skrish_iyer {} 18225b6a6f1Skrish_iyer }; 18325b6a6f1Skrish_iyer 18425b6a6f1Skrish_iyer 18525b6a6f1Skrish_iyer module_info* modules[] = { 18625b6a6f1Skrish_iyer (module_info*)&mmc_bus_controller_module, 18725b6a6f1Skrish_iyer (module_info*)&mmc_bus_device_module, 18825b6a6f1Skrish_iyer NULL 18925b6a6f1Skrish_iyer }; 190