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 { 5224136793SAdrien 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 81*5ec64c5cSAdrien Destugues mmc_bus_execute_command(device_node* node, void* cookie, uint16_t rca, 82*5ec64c5cSAdrien Destugues uint8_t command, uint32_t argument, uint32_t* result) 8362eaf4c0SAdrien Destugues { 8462eaf4c0SAdrien Destugues TRACE("In mmc_bus_execute_command\n"); 8562eaf4c0SAdrien Destugues 8674b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 8774b60970SAnarchos 8874b60970SAnarchos bus->AcquireBus(); 89522c141dSAdrien Destugues status_t error = bus->ExecuteCommand(rca, command, argument, result); 9074b60970SAnarchos bus->ReleaseBus(); 91*5ec64c5cSAdrien Destugues 9274b60970SAnarchos return error; 9374b60970SAnarchos } 9474b60970SAnarchos 9574b60970SAnarchos 9674b60970SAnarchos static status_t 97*5ec64c5cSAdrien Destugues mmc_bus_do_io(device_node* node, void* cookie, uint16_t rca, uint8_t command, 98d1fee57dSAdrien Destugues IOOperation* operation, bool offsetAsSectors) 9974b60970SAnarchos { 10074b60970SAnarchos MMCBus* bus = (MMCBus*)cookie; 1017a160a86SAdrien Destugues status_t result = B_OK; 1027a160a86SAdrien Destugues 103*5ec64c5cSAdrien Destugues bus->AcquireBus(); 104d1fee57dSAdrien Destugues result = bus->DoIO(rca, command, operation, offsetAsSectors); 10574b60970SAnarchos bus->ReleaseBus(); 106*5ec64c5cSAdrien Destugues 10774b60970SAnarchos return result; 10862eaf4c0SAdrien Destugues } 10962eaf4c0SAdrien Destugues 11062eaf4c0SAdrien Destugues 11134552f8eSAdrien Destugues static void 112*5ec64c5cSAdrien Destugues mmc_bus_set_width(device_node* node, void* cookie, int width) 11334552f8eSAdrien Destugues { 11434552f8eSAdrien Destugues MMCBus* bus = (MMCBus*)cookie; 11534552f8eSAdrien Destugues 11634552f8eSAdrien Destugues bus->AcquireBus(); 11734552f8eSAdrien Destugues bus->SetBusWidth(width); 11834552f8eSAdrien Destugues bus->ReleaseBus(); 11934552f8eSAdrien Destugues } 12034552f8eSAdrien Destugues 12134552f8eSAdrien Destugues 12262eaf4c0SAdrien Destugues static status_t 12325b6a6f1Skrish_iyer std_ops(int32 op, ...) 12425b6a6f1Skrish_iyer { 12525b6a6f1Skrish_iyer switch (op) { 12625b6a6f1Skrish_iyer case B_MODULE_INIT: 12725b6a6f1Skrish_iyer // Nothing to do 12825b6a6f1Skrish_iyer case B_MODULE_UNINIT: 12925b6a6f1Skrish_iyer return B_OK; 13025b6a6f1Skrish_iyer 13125b6a6f1Skrish_iyer default: 13225b6a6f1Skrish_iyer break; 13325b6a6f1Skrish_iyer } 13425b6a6f1Skrish_iyer 13525b6a6f1Skrish_iyer return B_ERROR; 13625b6a6f1Skrish_iyer } 13725b6a6f1Skrish_iyer 13825b6a6f1Skrish_iyer 13925b6a6f1Skrish_iyer driver_module_info mmc_bus_device_module = { 14025b6a6f1Skrish_iyer { 141ff76d2dfSAdrien Destugues MMC_BUS_DEVICE_NAME, 14225b6a6f1Skrish_iyer 0, 14325b6a6f1Skrish_iyer std_ops 14425b6a6f1Skrish_iyer }, 14525b6a6f1Skrish_iyer NULL, // supported devices 14625b6a6f1Skrish_iyer NULL, // register node 14725b6a6f1Skrish_iyer mmc_bus_init, 14825b6a6f1Skrish_iyer mmc_bus_uninit, 149dedbe94eSAdrien Destugues mmc_bus_register_child, 15025b6a6f1Skrish_iyer NULL, // rescan 15125b6a6f1Skrish_iyer mmc_bus_removed, 15225b6a6f1Skrish_iyer NULL, // suspend 15325b6a6f1Skrish_iyer NULL // resume 15425b6a6f1Skrish_iyer }; 15525b6a6f1Skrish_iyer 15625b6a6f1Skrish_iyer 15762eaf4c0SAdrien Destugues mmc_device_interface mmc_bus_controller_module = { 15862eaf4c0SAdrien Destugues { 15925b6a6f1Skrish_iyer { 160ff76d2dfSAdrien Destugues MMC_BUS_MODULE_NAME, 16125b6a6f1Skrish_iyer 0, 16225b6a6f1Skrish_iyer &std_ops 16325b6a6f1Skrish_iyer }, 16425b6a6f1Skrish_iyer 16525b6a6f1Skrish_iyer NULL, // supported devices 16625b6a6f1Skrish_iyer mmc_bus_added_device, 16725b6a6f1Skrish_iyer NULL, 16825b6a6f1Skrish_iyer NULL, 16925b6a6f1Skrish_iyer NULL 17062eaf4c0SAdrien Destugues }, 17174b60970SAnarchos mmc_bus_execute_command, 17234552f8eSAdrien Destugues mmc_bus_do_io, 17334552f8eSAdrien Destugues mmc_bus_set_width 17425b6a6f1Skrish_iyer }; 17525b6a6f1Skrish_iyer 17625b6a6f1Skrish_iyer 17725b6a6f1Skrish_iyer module_dependency module_dependencies[] = { 17825b6a6f1Skrish_iyer { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 17925b6a6f1Skrish_iyer {} 18025b6a6f1Skrish_iyer }; 18125b6a6f1Skrish_iyer 18225b6a6f1Skrish_iyer 18325b6a6f1Skrish_iyer module_info* modules[] = { 18425b6a6f1Skrish_iyer (module_info*)&mmc_bus_controller_module, 18525b6a6f1Skrish_iyer (module_info*)&mmc_bus_device_module, 18625b6a6f1Skrish_iyer NULL 18725b6a6f1Skrish_iyer }; 188