125b6a6f1Skrish_iyer /* 27a160a86SAdrien Destugues * Copyright 2018-2021 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 77a160a86SAdrien Destugues * Adrien Destugues, pulkomandy@pulkomandy.tk 825b6a6f1Skrish_iyer */ 925b6a6f1Skrish_iyer #include "mmc_bus.h" 1025b6a6f1Skrish_iyer 1125b6a6f1Skrish_iyer 12ff76d2dfSAdrien Destugues #define MMC_BUS_DEVICE_NAME "bus_managers/mmc_bus/device/v1" 13ff76d2dfSAdrien Destugues 14ff76d2dfSAdrien Destugues 1525b6a6f1Skrish_iyer device_manager_info* gDeviceManager = NULL; 1625b6a6f1Skrish_iyer 1725b6a6f1Skrish_iyer 1825b6a6f1Skrish_iyer static status_t 1925b6a6f1Skrish_iyer mmc_bus_init(device_node* node, void** _device) 2025b6a6f1Skrish_iyer { 2125b6a6f1Skrish_iyer CALLED(); 2225b6a6f1Skrish_iyer MMCBus* device = new(std::nothrow) MMCBus(node); 2325b6a6f1Skrish_iyer if (device == NULL) { 2425b6a6f1Skrish_iyer ERROR("Unable to allocate MMC bus\n"); 2525b6a6f1Skrish_iyer return B_NO_MEMORY; 2625b6a6f1Skrish_iyer } 2725b6a6f1Skrish_iyer 2825b6a6f1Skrish_iyer status_t result = device->InitCheck(); 2925b6a6f1Skrish_iyer if (result != B_OK) { 3025b6a6f1Skrish_iyer TRACE("failed to set up mmc bus device object\n"); 3125b6a6f1Skrish_iyer return result; 3225b6a6f1Skrish_iyer } 3325b6a6f1Skrish_iyer TRACE("MMC bus object created\n"); 3425b6a6f1Skrish_iyer 3525b6a6f1Skrish_iyer *_device = device; 3625b6a6f1Skrish_iyer return B_OK; 3725b6a6f1Skrish_iyer } 3825b6a6f1Skrish_iyer 3925b6a6f1Skrish_iyer 4025b6a6f1Skrish_iyer static void 4125b6a6f1Skrish_iyer mmc_bus_uninit(void* _device) 4225b6a6f1Skrish_iyer { 4325b6a6f1Skrish_iyer CALLED(); 4425b6a6f1Skrish_iyer MMCBus* device = (MMCBus*)_device; 4525b6a6f1Skrish_iyer delete device; 4625b6a6f1Skrish_iyer } 4725b6a6f1Skrish_iyer 4825b6a6f1Skrish_iyer 49dedbe94eSAdrien Destugues static status_t 50dedbe94eSAdrien Destugues mmc_bus_register_child(void* _device) 51dedbe94eSAdrien Destugues { 52dedbe94eSAdrien Destugues CALLED(); 53dedbe94eSAdrien Destugues MMCBus* device = (MMCBus*)_device; 54dedbe94eSAdrien Destugues device->Rescan(); 55dedbe94eSAdrien Destugues return B_OK; 56dedbe94eSAdrien Destugues } 57dedbe94eSAdrien Destugues 58dedbe94eSAdrien Destugues 5925b6a6f1Skrish_iyer static void 6025b6a6f1Skrish_iyer mmc_bus_removed(void* _device) 6125b6a6f1Skrish_iyer { 6225b6a6f1Skrish_iyer CALLED(); 6325b6a6f1Skrish_iyer } 6425b6a6f1Skrish_iyer 6525b6a6f1Skrish_iyer 6625b6a6f1Skrish_iyer status_t 6725b6a6f1Skrish_iyer mmc_bus_added_device(device_node* parent) 6825b6a6f1Skrish_iyer { 6925b6a6f1Skrish_iyer CALLED(); 7025b6a6f1Skrish_iyer 7125b6a6f1Skrish_iyer device_attr attributes[] = { 72dedbe94eSAdrien Destugues { B_DEVICE_BUS, B_STRING_TYPE, { string: "mmc"}}, 73dedbe94eSAdrien Destugues { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "MMC bus root"}}, 7425b6a6f1Skrish_iyer { NULL } 7525b6a6f1Skrish_iyer }; 7625b6a6f1Skrish_iyer 77ff76d2dfSAdrien Destugues return gDeviceManager->register_node(parent, MMC_BUS_DEVICE_NAME, 7825b6a6f1Skrish_iyer attributes, NULL, NULL); 7925b6a6f1Skrish_iyer } 8025b6a6f1Skrish_iyer 8125b6a6f1Skrish_iyer 8225b6a6f1Skrish_iyer static status_t 8362eaf4c0SAdrien Destugues mmc_bus_execute_command(device_node* node, uint8_t command, uint32_t argument, 8462eaf4c0SAdrien Destugues uint32_t* result) 8562eaf4c0SAdrien Destugues { 8674b60970SAnarchos // FIXME store the parent cookie in the bus cookie or something instead of 8774b60970SAnarchos // getting/putting the parent each time. 8874b60970SAnarchos driver_module_info* mmc; 8962eaf4c0SAdrien Destugues void* cookie; 9062eaf4c0SAdrien Destugues 9162eaf4c0SAdrien Destugues TRACE("In mmc_bus_execute_command\n"); 9262eaf4c0SAdrien Destugues device_node* parent = gDeviceManager->get_parent_node(node); 9374b60970SAnarchos gDeviceManager->get_driver(parent, &mmc, &cookie); 9462eaf4c0SAdrien Destugues gDeviceManager->put_node(parent); 9562eaf4c0SAdrien Destugues 9674b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 9774b60970SAnarchos 9874b60970SAnarchos bus->AcquireBus(); 9974b60970SAnarchos status_t error = bus->ExecuteCommand(command, argument, result); 10074b60970SAnarchos bus->ReleaseBus(); 10174b60970SAnarchos return error; 10274b60970SAnarchos } 10374b60970SAnarchos 10474b60970SAnarchos 10574b60970SAnarchos static status_t 1069a37366bSAdrien Destugues mmc_bus_do_io(device_node* node, uint16_t rca, uint8_t command, 107*d1fee57dSAdrien Destugues IOOperation* operation, bool offsetAsSectors) 10874b60970SAnarchos { 10974b60970SAnarchos driver_module_info* mmc; 11074b60970SAnarchos void* cookie; 11174b60970SAnarchos 1127a160a86SAdrien Destugues // FIXME store the parent cookie in the bus cookie or something instead of 1137a160a86SAdrien Destugues // getting/putting the parent each time. 11474b60970SAnarchos device_node* parent = gDeviceManager->get_parent_node(node); 11574b60970SAnarchos gDeviceManager->get_driver(parent, &mmc, &cookie); 11674b60970SAnarchos gDeviceManager->put_node(parent); 11774b60970SAnarchos 11874b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 11974b60970SAnarchos bus->AcquireBus(); 1207a160a86SAdrien Destugues status_t result = B_OK; 1217a160a86SAdrien Destugues 122*d1fee57dSAdrien Destugues result = bus->DoIO(rca, command, operation, offsetAsSectors); 1237a160a86SAdrien Destugues 12474b60970SAnarchos bus->ReleaseBus(); 12574b60970SAnarchos return result; 12662eaf4c0SAdrien Destugues } 12762eaf4c0SAdrien Destugues 12862eaf4c0SAdrien Destugues 12962eaf4c0SAdrien Destugues static status_t 13025b6a6f1Skrish_iyer std_ops(int32 op, ...) 13125b6a6f1Skrish_iyer { 13225b6a6f1Skrish_iyer switch (op) { 13325b6a6f1Skrish_iyer case B_MODULE_INIT: 13425b6a6f1Skrish_iyer // Nothing to do 13525b6a6f1Skrish_iyer case B_MODULE_UNINIT: 13625b6a6f1Skrish_iyer return B_OK; 13725b6a6f1Skrish_iyer 13825b6a6f1Skrish_iyer default: 13925b6a6f1Skrish_iyer break; 14025b6a6f1Skrish_iyer } 14125b6a6f1Skrish_iyer 14225b6a6f1Skrish_iyer return B_ERROR; 14325b6a6f1Skrish_iyer } 14425b6a6f1Skrish_iyer 14525b6a6f1Skrish_iyer 14625b6a6f1Skrish_iyer driver_module_info mmc_bus_device_module = { 14725b6a6f1Skrish_iyer { 148ff76d2dfSAdrien Destugues MMC_BUS_DEVICE_NAME, 14925b6a6f1Skrish_iyer 0, 15025b6a6f1Skrish_iyer std_ops 15125b6a6f1Skrish_iyer }, 15225b6a6f1Skrish_iyer NULL, // supported devices 15325b6a6f1Skrish_iyer NULL, // register node 15425b6a6f1Skrish_iyer mmc_bus_init, 15525b6a6f1Skrish_iyer mmc_bus_uninit, 156dedbe94eSAdrien Destugues mmc_bus_register_child, 15725b6a6f1Skrish_iyer NULL, // rescan 15825b6a6f1Skrish_iyer mmc_bus_removed, 15925b6a6f1Skrish_iyer NULL, // suspend 16025b6a6f1Skrish_iyer NULL // resume 16125b6a6f1Skrish_iyer }; 16225b6a6f1Skrish_iyer 16325b6a6f1Skrish_iyer 16462eaf4c0SAdrien Destugues mmc_device_interface mmc_bus_controller_module = { 16562eaf4c0SAdrien Destugues { 16625b6a6f1Skrish_iyer { 167ff76d2dfSAdrien Destugues MMC_BUS_MODULE_NAME, 16825b6a6f1Skrish_iyer 0, 16925b6a6f1Skrish_iyer &std_ops 17025b6a6f1Skrish_iyer }, 17125b6a6f1Skrish_iyer 17225b6a6f1Skrish_iyer NULL, // supported devices 17325b6a6f1Skrish_iyer mmc_bus_added_device, 17425b6a6f1Skrish_iyer NULL, 17525b6a6f1Skrish_iyer NULL, 17625b6a6f1Skrish_iyer NULL 17762eaf4c0SAdrien Destugues }, 17874b60970SAnarchos mmc_bus_execute_command, 1797a160a86SAdrien Destugues mmc_bus_do_io 18025b6a6f1Skrish_iyer }; 18125b6a6f1Skrish_iyer 18225b6a6f1Skrish_iyer 18325b6a6f1Skrish_iyer module_dependency module_dependencies[] = { 18425b6a6f1Skrish_iyer { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 18525b6a6f1Skrish_iyer {} 18625b6a6f1Skrish_iyer }; 18725b6a6f1Skrish_iyer 18825b6a6f1Skrish_iyer 18925b6a6f1Skrish_iyer module_info* modules[] = { 19025b6a6f1Skrish_iyer (module_info*)&mmc_bus_controller_module, 19125b6a6f1Skrish_iyer (module_info*)&mmc_bus_device_module, 19225b6a6f1Skrish_iyer NULL 19325b6a6f1Skrish_iyer }; 194