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 { 52*24136793SAdrien Destugues // Nothing to do, child devices are registered by the scanning thread 53dedbe94eSAdrien Destugues return B_OK; 54dedbe94eSAdrien Destugues } 55dedbe94eSAdrien Destugues 56dedbe94eSAdrien Destugues 5725b6a6f1Skrish_iyer static void 5825b6a6f1Skrish_iyer mmc_bus_removed(void* _device) 5925b6a6f1Skrish_iyer { 6025b6a6f1Skrish_iyer CALLED(); 6125b6a6f1Skrish_iyer } 6225b6a6f1Skrish_iyer 6325b6a6f1Skrish_iyer 6425b6a6f1Skrish_iyer status_t 6525b6a6f1Skrish_iyer mmc_bus_added_device(device_node* parent) 6625b6a6f1Skrish_iyer { 6725b6a6f1Skrish_iyer CALLED(); 6825b6a6f1Skrish_iyer 6925b6a6f1Skrish_iyer device_attr attributes[] = { 70dedbe94eSAdrien Destugues { B_DEVICE_BUS, B_STRING_TYPE, { string: "mmc"}}, 71dedbe94eSAdrien Destugues { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "MMC bus root"}}, 7225b6a6f1Skrish_iyer { NULL } 7325b6a6f1Skrish_iyer }; 7425b6a6f1Skrish_iyer 75ff76d2dfSAdrien Destugues return gDeviceManager->register_node(parent, MMC_BUS_DEVICE_NAME, 7625b6a6f1Skrish_iyer attributes, NULL, NULL); 7725b6a6f1Skrish_iyer } 7825b6a6f1Skrish_iyer 7925b6a6f1Skrish_iyer 8025b6a6f1Skrish_iyer static status_t 8162eaf4c0SAdrien Destugues mmc_bus_execute_command(device_node* node, uint8_t command, uint32_t argument, 8262eaf4c0SAdrien Destugues uint32_t* result) 8362eaf4c0SAdrien Destugues { 8474b60970SAnarchos // FIXME store the parent cookie in the bus cookie or something instead of 8574b60970SAnarchos // getting/putting the parent each time. 8674b60970SAnarchos driver_module_info* mmc; 8762eaf4c0SAdrien Destugues void* cookie; 8862eaf4c0SAdrien Destugues 8962eaf4c0SAdrien Destugues TRACE("In mmc_bus_execute_command\n"); 9062eaf4c0SAdrien Destugues device_node* parent = gDeviceManager->get_parent_node(node); 9174b60970SAnarchos gDeviceManager->get_driver(parent, &mmc, &cookie); 9262eaf4c0SAdrien Destugues gDeviceManager->put_node(parent); 9362eaf4c0SAdrien Destugues 9474b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 9574b60970SAnarchos 9674b60970SAnarchos bus->AcquireBus(); 9774b60970SAnarchos status_t error = bus->ExecuteCommand(command, argument, result); 9874b60970SAnarchos bus->ReleaseBus(); 9974b60970SAnarchos return error; 10074b60970SAnarchos } 10174b60970SAnarchos 10274b60970SAnarchos 10374b60970SAnarchos static status_t 1049a37366bSAdrien Destugues mmc_bus_do_io(device_node* node, uint16_t rca, uint8_t command, 105d1fee57dSAdrien Destugues IOOperation* operation, bool offsetAsSectors) 10674b60970SAnarchos { 10774b60970SAnarchos driver_module_info* mmc; 10874b60970SAnarchos void* cookie; 10974b60970SAnarchos 1107a160a86SAdrien Destugues // FIXME store the parent cookie in the bus cookie or something instead of 1117a160a86SAdrien Destugues // getting/putting the parent each time. 11274b60970SAnarchos device_node* parent = gDeviceManager->get_parent_node(node); 11374b60970SAnarchos gDeviceManager->get_driver(parent, &mmc, &cookie); 11474b60970SAnarchos gDeviceManager->put_node(parent); 11574b60970SAnarchos 11674b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 11774b60970SAnarchos bus->AcquireBus(); 1187a160a86SAdrien Destugues status_t result = B_OK; 1197a160a86SAdrien Destugues 120d1fee57dSAdrien Destugues result = bus->DoIO(rca, command, operation, offsetAsSectors); 1217a160a86SAdrien Destugues 12274b60970SAnarchos bus->ReleaseBus(); 12374b60970SAnarchos return result; 12462eaf4c0SAdrien Destugues } 12562eaf4c0SAdrien Destugues 12662eaf4c0SAdrien Destugues 12762eaf4c0SAdrien Destugues static status_t 12825b6a6f1Skrish_iyer std_ops(int32 op, ...) 12925b6a6f1Skrish_iyer { 13025b6a6f1Skrish_iyer switch (op) { 13125b6a6f1Skrish_iyer case B_MODULE_INIT: 13225b6a6f1Skrish_iyer // Nothing to do 13325b6a6f1Skrish_iyer case B_MODULE_UNINIT: 13425b6a6f1Skrish_iyer return B_OK; 13525b6a6f1Skrish_iyer 13625b6a6f1Skrish_iyer default: 13725b6a6f1Skrish_iyer break; 13825b6a6f1Skrish_iyer } 13925b6a6f1Skrish_iyer 14025b6a6f1Skrish_iyer return B_ERROR; 14125b6a6f1Skrish_iyer } 14225b6a6f1Skrish_iyer 14325b6a6f1Skrish_iyer 14425b6a6f1Skrish_iyer driver_module_info mmc_bus_device_module = { 14525b6a6f1Skrish_iyer { 146ff76d2dfSAdrien Destugues MMC_BUS_DEVICE_NAME, 14725b6a6f1Skrish_iyer 0, 14825b6a6f1Skrish_iyer std_ops 14925b6a6f1Skrish_iyer }, 15025b6a6f1Skrish_iyer NULL, // supported devices 15125b6a6f1Skrish_iyer NULL, // register node 15225b6a6f1Skrish_iyer mmc_bus_init, 15325b6a6f1Skrish_iyer mmc_bus_uninit, 154dedbe94eSAdrien Destugues mmc_bus_register_child, 15525b6a6f1Skrish_iyer NULL, // rescan 15625b6a6f1Skrish_iyer mmc_bus_removed, 15725b6a6f1Skrish_iyer NULL, // suspend 15825b6a6f1Skrish_iyer NULL // resume 15925b6a6f1Skrish_iyer }; 16025b6a6f1Skrish_iyer 16125b6a6f1Skrish_iyer 16262eaf4c0SAdrien Destugues mmc_device_interface mmc_bus_controller_module = { 16362eaf4c0SAdrien Destugues { 16425b6a6f1Skrish_iyer { 165ff76d2dfSAdrien Destugues MMC_BUS_MODULE_NAME, 16625b6a6f1Skrish_iyer 0, 16725b6a6f1Skrish_iyer &std_ops 16825b6a6f1Skrish_iyer }, 16925b6a6f1Skrish_iyer 17025b6a6f1Skrish_iyer NULL, // supported devices 17125b6a6f1Skrish_iyer mmc_bus_added_device, 17225b6a6f1Skrish_iyer NULL, 17325b6a6f1Skrish_iyer NULL, 17425b6a6f1Skrish_iyer NULL 17562eaf4c0SAdrien Destugues }, 17674b60970SAnarchos mmc_bus_execute_command, 1777a160a86SAdrien Destugues mmc_bus_do_io 17825b6a6f1Skrish_iyer }; 17925b6a6f1Skrish_iyer 18025b6a6f1Skrish_iyer 18125b6a6f1Skrish_iyer module_dependency module_dependencies[] = { 18225b6a6f1Skrish_iyer { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 18325b6a6f1Skrish_iyer {} 18425b6a6f1Skrish_iyer }; 18525b6a6f1Skrish_iyer 18625b6a6f1Skrish_iyer 18725b6a6f1Skrish_iyer module_info* modules[] = { 18825b6a6f1Skrish_iyer (module_info*)&mmc_bus_controller_module, 18925b6a6f1Skrish_iyer (module_info*)&mmc_bus_device_module, 19025b6a6f1Skrish_iyer NULL 19125b6a6f1Skrish_iyer }; 192