1/*
2 * Copyright 2018-2021 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		B Krishnan Iyer, krishnaniyer97@gmail.com
7 *		Adrien Destugues, pulkomandy@pulkomandy.tk
8 */
9#include "mmc_bus.h"
10
11
12#define	MMC_BUS_DEVICE_NAME "bus_managers/mmc_bus/device/v1"
13
14
15device_manager_info* gDeviceManager = NULL;
16
17
18static status_t
19mmc_bus_init(device_node* node, void** _device)
20{
21	CALLED();
22	MMCBus* device = new(std::nothrow) MMCBus(node);
23	if (device == NULL) {
24		ERROR("Unable to allocate MMC bus\n");
25		return B_NO_MEMORY;
26	}
27
28	status_t result = device->InitCheck();
29	if (result != B_OK) {
30		TRACE("failed to set up mmc bus device object\n");
31		return result;
32	}
33	TRACE("MMC bus object created\n");
34
35	*_device = device;
36	return B_OK;
37}
38
39
40static void
41mmc_bus_uninit(void* _device)
42{
43	CALLED();
44	MMCBus* device = (MMCBus*)_device;
45	delete device;
46}
47
48
49static status_t
50mmc_bus_register_child(void* _device)
51{
52	// Nothing to do, child devices are registered by the scanning thread
53	return B_OK;
54}
55
56
57static void
58mmc_bus_removed(void* _device)
59{
60	CALLED();
61}
62
63
64status_t
65mmc_bus_added_device(device_node* parent)
66{
67	CALLED();
68
69	device_attr attributes[] = {
70		{ B_DEVICE_BUS, B_STRING_TYPE, { .string = "mmc"}},
71		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "MMC bus root"}},
72		{ NULL }
73	};
74
75	return gDeviceManager->register_node(parent, MMC_BUS_DEVICE_NAME,
76		attributes, NULL, NULL);
77}
78
79
80static status_t
81mmc_bus_execute_command(device_node* node, void* cookie, uint16_t rca,
82	uint8_t command, uint32_t argument, uint32_t* result)
83{
84	TRACE("In mmc_bus_execute_command\n");
85
86	MMCBus* bus = (MMCBus*)cookie;
87
88	bus->AcquireBus();
89	status_t error = bus->ExecuteCommand(rca, command, argument, result);
90	bus->ReleaseBus();
91
92	return error;
93}
94
95
96static status_t
97mmc_bus_do_io(device_node* node, void* cookie, uint16_t rca, uint8_t command,
98	IOOperation* operation, bool offsetAsSectors)
99{
100	MMCBus* bus = (MMCBus*)cookie;
101	status_t result = B_OK;
102
103	bus->AcquireBus();
104	result = bus->DoIO(rca, command, operation, offsetAsSectors);
105	bus->ReleaseBus();
106
107	return result;
108}
109
110
111static void
112mmc_bus_set_width(device_node* node, void* cookie, int width)
113{
114	MMCBus* bus = (MMCBus*)cookie;
115
116	bus->AcquireBus();
117	bus->SetBusWidth(width);
118	bus->ReleaseBus();
119}
120
121
122static status_t
123std_ops(int32 op, ...)
124{
125	switch (op) {
126		case B_MODULE_INIT:
127			// Nothing to do
128		case B_MODULE_UNINIT:
129			return B_OK;
130
131		default:
132			break;
133	}
134
135	return B_ERROR;
136}
137
138
139driver_module_info mmc_bus_device_module = {
140	{
141		MMC_BUS_DEVICE_NAME,
142		0,
143		std_ops
144	},
145	NULL, // supported devices
146	NULL, // register node
147	mmc_bus_init,
148	mmc_bus_uninit,
149	mmc_bus_register_child,
150	NULL, // rescan
151	mmc_bus_removed,
152	NULL, // suspend
153	NULL // resume
154};
155
156
157mmc_device_interface mmc_bus_controller_module = {
158	{
159		{
160			MMC_BUS_MODULE_NAME,
161			0,
162			&std_ops
163		},
164
165		NULL, // supported devices
166		mmc_bus_added_device,
167		NULL,
168		NULL,
169		NULL
170	},
171	mmc_bus_execute_command,
172	mmc_bus_do_io,
173	mmc_bus_set_width
174};
175
176
177module_dependency module_dependencies[] = {
178	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
179	{}
180};
181
182
183module_info* modules[] = {
184	(module_info*)&mmc_bus_controller_module,
185	(module_info*)&mmc_bus_device_module,
186	NULL
187};
188