1/*
2 * Copyright 2018-2021 Haiku, Inc. All rights reserved.
3 * Copyright 2020, Viveris Technologies.
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 *		B Krishnan Iyer, krishnaniyer97@gmail.com
8 *		Adrien Destugues, pulkomandy@pulkomandy.tk
9 */
10
11#include <new>
12
13#include <ctype.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17
18#include "mmc_disk.h"
19#include "mmc_icon.h"
20#include "mmc.h"
21
22#include <drivers/device_manager.h>
23#include <drivers/KernelExport.h>
24#include <drivers/Drivers.h>
25#include <kernel/OS.h>
26#include <util/fs_trim_support.h>
27
28#include <AutoDeleter.h>
29
30
31#define TRACE_MMC_DISK
32#ifdef TRACE_MMC_DISK
33#	define TRACE(x...) dprintf("\33[33mmmc_disk:\33[0m " x)
34#else
35#	define TRACE(x...) ;
36#endif
37#define ERROR(x...)			dprintf("\33[33mmmc_disk:\33[0m " x)
38#define CALLED() 			TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
39
40#define MMC_DISK_DRIVER_MODULE_NAME "drivers/disk/mmc/mmc_disk/driver_v1"
41#define MMC_DISK_DEVICE_MODULE_NAME "drivers/disk/mmc/mmc_disk/device_v1"
42#define MMC_DEVICE_ID_GENERATOR "mmc/device_id"
43
44
45static const uint32 kBlockSize = 512; // FIXME get it from the CSD
46
47static device_manager_info* sDeviceManager;
48
49
50struct mmc_disk_csd {
51	// The content of this register is described in Physical Layer Simplified
52	// Specification Version 8.00, section 5.3
53	uint64 bits[2];
54
55	uint8 structure_version() { return bits[1] >> 54; }
56	uint8 read_bl_len() { return (bits[1] >> 8) & 0xF; }
57	uint32 c_size()
58	{
59		if (structure_version() == 0)
60			return ((bits[0] >> 54) & 0x3FF) | ((bits[1] & 0x3) << 10);
61		if (structure_version() == 1)
62			return (bits[0] >> 40) & 0x3FFFFF;
63		return ((bits[0] >> 40) & 0xFFFFFF) | ((bits[1] & 0xF) << 24);
64	}
65
66	uint8 c_size_mult()
67	{
68		if (structure_version() == 0)
69			return (bits[0] >> 39) & 0x7;
70		// In later versions this field is not present in the structure and a
71		// fixed value is used.
72		return 8;
73	}
74};
75
76
77static float
78mmc_disk_supports_device(device_node* parent)
79{
80	// Filter all devices that are not on an MMC bus
81	const char* bus;
82	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus,
83			true) != B_OK)
84		return -1;
85
86	if (strcmp(bus, "mmc") != 0)
87		return 0.0;
88
89	CALLED();
90
91	// Filter all devices that are not of the known types
92	uint8_t deviceType;
93	if (sDeviceManager->get_attr_uint8(parent, kMmcTypeAttribute,
94			&deviceType, true) != B_OK)
95	{
96		ERROR("Could not get device type\n");
97		return -1;
98	}
99
100	if (deviceType == CARD_TYPE_SD)
101		TRACE("SD card found, parent: %p\n", parent);
102	else if (deviceType == CARD_TYPE_SDHC)
103		TRACE("SDHC card found, parent: %p\n", parent);
104	else
105		return 0.0;
106
107	return 0.8;
108}
109
110
111static status_t
112mmc_disk_register_device(device_node* node)
113{
114	CALLED();
115
116	device_attr attrs[] = {
117		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = "SD Card" }},
118		{ NULL }
119	};
120
121	return sDeviceManager->register_node(node, MMC_DISK_DRIVER_MODULE_NAME,
122		attrs, NULL, NULL);
123}
124
125
126static status_t
127mmc_disk_execute_iorequest(void* data, IOOperation* operation)
128{
129	mmc_disk_driver_info* info = (mmc_disk_driver_info*)data;
130	status_t error;
131
132	uint8_t command;
133	if (operation->IsWrite())
134		command = SD_WRITE_MULTIPLE_BLOCKS;
135	else
136		command = SD_READ_MULTIPLE_BLOCKS;
137	error = info->mmc->do_io(info->parent, info->parentCookie, info->rca,
138		command, operation, (info->flags & kIoCommandOffsetAsSectors) != 0);
139
140	if (error != B_OK) {
141		info->scheduler->OperationCompleted(operation, error, 0);
142		return error;
143	}
144
145	info->scheduler->OperationCompleted(operation, B_OK, operation->Length());
146	return B_OK;
147}
148
149
150static status_t
151mmc_block_get_geometry(mmc_disk_driver_info* info, device_geometry* geometry)
152{
153	struct mmc_disk_csd csd;
154	TRACE("Get geometry\n");
155	status_t error = info->mmc->execute_command(info->parent,
156		info->parentCookie, 0, SD_SEND_CSD, info->rca << 16, (uint32_t*)&csd);
157	if (error != B_OK) {
158		TRACE("Could not get CSD! %s\n", strerror(error));
159		return error;
160	}
161
162	TRACE("CSD: %" PRIx64 " %" PRIx64 "\n", csd.bits[0], csd.bits[1]);
163
164	if (csd.structure_version() >= 3) {
165		TRACE("unknown CSD version %d\n", csd.structure_version());
166		return B_NOT_SUPPORTED;
167	}
168
169	geometry->bytes_per_sector = 1 << csd.read_bl_len();
170	geometry->sectors_per_track = csd.c_size() + 1;
171	geometry->cylinder_count = 1 << (csd.c_size_mult() + 2);
172	geometry->head_count = 1;
173	geometry->device_type = B_DISK;
174	geometry->removable = true; // TODO detect eMMC which isn't
175	geometry->read_only = false; // TODO check write protect switch?
176	geometry->write_once = false;
177
178	// This function will be called before all data transfers, so we use this
179	// opportunity to switch the card to 4-bit data transfers (instead of the
180	// default 1 bit mode)
181	uint32_t cardStatus;
182	const uint32 k4BitMode = 2;
183	info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
184		SD_APP_CMD, info->rca << 16, &cardStatus);
185	info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
186		SD_SET_BUS_WIDTH, k4BitMode, &cardStatus);
187
188	// From now on we use 4 bit mode
189	info->mmc->set_bus_width(info->parent, info->parentCookie, 4);
190
191	return B_OK;
192}
193
194
195static status_t
196mmc_disk_init_driver(device_node* node, void** cookie)
197{
198	CALLED();
199	mmc_disk_driver_info* info = (mmc_disk_driver_info*)malloc(
200		sizeof(mmc_disk_driver_info));
201
202	if (info == NULL)
203		return B_NO_MEMORY;
204
205	memset(info, 0, sizeof(*info));
206
207	void* unused2;
208	info->node = node;
209	info->parent = sDeviceManager->get_parent_node(info->node);
210	sDeviceManager->get_driver(info->parent, (driver_module_info **)&info->mmc,
211		&unused2);
212
213	// We need to grab the bus cookie as well
214	// FIXME it would be easier if that was available from the get_driver call
215	// above directly, but currently it isn't.
216	device_node* busNode = sDeviceManager->get_parent_node(info->parent);
217	driver_module_info* unused;
218	sDeviceManager->get_driver(busNode, &unused, &info->parentCookie);
219	sDeviceManager->put_node(busNode);
220
221	TRACE("MMC bus handle: %p %s\n", info->mmc, info->mmc->info.info.name);
222
223	if (sDeviceManager->get_attr_uint16(node, kMmcRcaAttribute, &info->rca,
224			true) != B_OK) {
225		TRACE("MMC card node has no RCA attribute\n");
226		free(info);
227		return B_BAD_DATA;
228	}
229
230	uint8_t deviceType;
231	if (sDeviceManager->get_attr_uint8(info->parent, kMmcTypeAttribute,
232			&deviceType, true) != B_OK) {
233		ERROR("Could not get device type\n");
234		free(info);
235		return B_BAD_DATA;
236	}
237
238	// SD and MMC cards use byte offsets for IO commands, later ones (SDHC,
239	// SDXC, ...) use sectors.
240	if (deviceType == CARD_TYPE_SD || deviceType == CARD_TYPE_MMC)
241		info->flags = 0;
242	else
243		info->flags = kIoCommandOffsetAsSectors;
244
245	status_t error;
246
247	static const uint32 kDMAResourceBufferCount			= 16;
248	static const uint32 kDMAResourceBounceBufferCount	= 16;
249
250	info->dmaResource = new(std::nothrow) DMAResource;
251	if (info->dmaResource == NULL) {
252		TRACE("Failed to allocate DMA resource");
253		free(info);
254		return B_NO_MEMORY;
255	}
256
257	error = info->dmaResource->Init(info->node, kBlockSize,
258		kDMAResourceBufferCount, kDMAResourceBounceBufferCount);
259	if (error != B_OK) {
260		TRACE("Failed to init DMA resource");
261		delete info->dmaResource;
262		free(info);
263		return error;
264	}
265
266	info->scheduler = new(std::nothrow) IOSchedulerSimple(info->dmaResource);
267	if (info->scheduler == NULL) {
268		TRACE("Failed to allocate scheduler");
269		delete info->dmaResource;
270		free(info);
271		return B_NO_MEMORY;
272	}
273
274	error = info->scheduler->Init("mmc storage");
275	if (error != B_OK) {
276		TRACE("Failed to init scheduler");
277		delete info->scheduler;
278		delete info->dmaResource;
279		free(info);
280		return error;
281	}
282	info->scheduler->SetCallback(&mmc_disk_execute_iorequest, info);
283
284	memset(&info->geometry, 0, sizeof(info->geometry));
285
286	TRACE("MMC card device initialized for RCA %x\n", info->rca);
287	*cookie = info;
288	return B_OK;
289}
290
291
292static void
293mmc_disk_uninit_driver(void* _cookie)
294{
295	CALLED();
296	mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie;
297	delete info->scheduler;
298	delete info->dmaResource;
299	sDeviceManager->put_node(info->parent);
300	free(info);
301}
302
303
304static status_t
305mmc_disk_register_child_devices(void* _cookie)
306{
307	CALLED();
308	mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie;
309	status_t status;
310
311	int32 id = sDeviceManager->create_id(MMC_DEVICE_ID_GENERATOR);
312	if (id < 0)
313		return id;
314
315	char name[64];
316	snprintf(name, sizeof(name), "disk/mmc/%" B_PRId32 "/raw", id);
317
318	status = sDeviceManager->publish_device(info->node, name,
319		MMC_DISK_DEVICE_MODULE_NAME);
320
321	return status;
322}
323
324
325//	#pragma mark - device module API
326
327
328static status_t
329mmc_block_init_device(void* _info, void** _cookie)
330{
331	CALLED();
332
333	// No additional context, so just reuse the same data as the disk device
334	mmc_disk_driver_info* info = (mmc_disk_driver_info*)_info;
335	*_cookie = info;
336
337	// Note: it is not possible to execute commands here, because this is called
338	// with the mmc_bus locked for enumeration (and still using slow clock).
339
340	return B_OK;
341}
342
343
344static void
345mmc_block_uninit_device(void* _cookie)
346{
347	CALLED();
348	//mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie;
349
350	// TODO cleanup whatever is relevant
351}
352
353
354static status_t
355mmc_block_open(void* _info, const char* path, int openMode, void** _cookie)
356{
357	CALLED();
358	mmc_disk_driver_info* info = (mmc_disk_driver_info*)_info;
359
360	// allocate cookie
361	mmc_disk_handle* handle = new(std::nothrow) mmc_disk_handle;
362	*_cookie = handle;
363	if (handle == NULL) {
364		return B_NO_MEMORY;
365	}
366	handle->info = info;
367
368	return B_OK;
369}
370
371
372static status_t
373mmc_block_close(void* cookie)
374{
375	//mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
376	CALLED();
377
378	return B_OK;
379}
380
381
382static status_t
383mmc_block_free(void* cookie)
384{
385	CALLED();
386	mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
387
388	delete handle;
389	return B_OK;
390}
391
392
393static status_t
394mmc_block_read(void* cookie, off_t pos, void* buffer, size_t* _length)
395{
396	CALLED();
397	mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
398
399	size_t length = *_length;
400
401	if (handle->info->geometry.bytes_per_sector == 0) {
402		status_t error = mmc_block_get_geometry(handle->info,
403			&handle->info->geometry);
404		if (error != B_OK) {
405			TRACE("Failed to get disk capacity");
406			return error;
407		}
408	}
409
410	// Do not allow reading past device end
411	if (pos >= handle->info->DeviceSize())
412		return B_BAD_VALUE;
413	if (pos + (off_t)length > handle->info->DeviceSize())
414		length = handle->info->DeviceSize() - pos;
415
416	IORequest request;
417	status_t status = request.Init(pos, (addr_t)buffer, length, false, 0);
418	if (status != B_OK)
419		return status;
420
421	status = handle->info->scheduler->ScheduleRequest(&request);
422	if (status != B_OK)
423		return status;
424
425	status = request.Wait(0, 0);
426	if (status == B_OK)
427		*_length = length;
428	return status;
429}
430
431
432static status_t
433mmc_block_write(void* cookie, off_t position, const void* buffer,
434	size_t* _length)
435{
436	CALLED();
437	mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
438
439	size_t length = *_length;
440
441	if (handle->info->geometry.bytes_per_sector == 0) {
442		status_t error = mmc_block_get_geometry(handle->info,
443			&handle->info->geometry);
444		if (error != B_OK) {
445			TRACE("Failed to get disk capacity");
446			return error;
447		}
448	}
449
450	if (position >= handle->info->DeviceSize())
451		return B_BAD_VALUE;
452	if (position + (off_t)length > handle->info->DeviceSize())
453		length = handle->info->DeviceSize() - position;
454
455	IORequest request;
456	status_t status = request.Init(position, (addr_t)buffer, length, true, 0);
457	if (status != B_OK)
458		return status;
459
460	status = handle->info->scheduler->ScheduleRequest(&request);
461	if (status != B_OK)
462		return status;
463
464	status = request.Wait(0, 0);
465	if (status == B_OK)
466		*_length = length;
467
468	return status;
469}
470
471
472static status_t
473mmc_block_io(void* cookie, io_request* request)
474{
475	CALLED();
476	mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
477
478	return handle->info->scheduler->ScheduleRequest(request);
479}
480
481
482static status_t
483mmc_block_trim(mmc_disk_driver_info* info, fs_trim_data* trimData)
484{
485	enum {
486		kEraseModeErase = 0, // force to actually erase the data
487		kEraseModeDiscard = 1,
488			// just mark the data as unused for internal wear leveling
489			// algorithms
490		kEraseModeFullErase = 2, // erase the whole card
491	};
492	TRACE("trim_device()\n");
493
494	trimData->trimmed_size = 0;
495
496	const off_t deviceSize = info->DeviceSize(); // in bytes
497	if (deviceSize < 0)
498		return B_BAD_VALUE;
499
500	STATIC_ASSERT(sizeof(deviceSize) <= sizeof(uint64));
501	ASSERT(deviceSize >= 0);
502
503	// Do not trim past device end
504	for (uint32 i = 0; i < trimData->range_count; i++) {
505		uint64 offset = trimData->ranges[i].offset;
506		uint64& size = trimData->ranges[i].size;
507
508		if (offset >= (uint64)deviceSize)
509			return B_BAD_VALUE;
510		size = min_c(size, (uint64)deviceSize - offset);
511	}
512
513	uint64 trimmedSize = 0;
514	status_t result = B_OK;
515	for (uint32 i = 0; i < trimData->range_count; i++) {
516		uint64 offset = trimData->ranges[i].offset;
517		uint64 length = trimData->ranges[i].size;
518
519		// Round up offset and length to multiple of the sector size
520		// The offset is rounded up, so some space may be left
521		// (not trimmed) at the start of the range.
522		offset = ROUNDUP(offset, kBlockSize);
523		// Adjust the length for the possibly skipped range
524		length -= offset - trimData->ranges[i].offset;
525		// The length is rounded down, so some space at the end may also
526		// be left (not trimmed).
527		length &= ~(kBlockSize - 1);
528
529		if (length == 0)
530			continue;
531
532		TRACE("trim %" B_PRIu64 " bytes from %" B_PRIu64 "\n",
533			length, offset);
534
535		ASSERT(offset % kBlockSize == 0);
536		ASSERT(length % kBlockSize == 0);
537
538		if ((info->flags & kIoCommandOffsetAsSectors) != 0) {
539			offset /= kBlockSize;
540			length /= kBlockSize;
541		}
542
543		// Parameter of execute_command is uint32_t
544		if (offset > UINT32_MAX
545			|| length > UINT32_MAX - offset) {
546			result = B_BAD_VALUE;
547			break;
548		}
549
550		uint32_t response;
551		result = info->mmc->execute_command(info->parent, info->parentCookie,
552			info->rca, SD_ERASE_WR_BLK_START, offset, &response);
553		if (result != B_OK)
554			break;
555		result = info->mmc->execute_command(info->parent, info->parentCookie,
556			info->rca, SD_ERASE_WR_BLK_END, offset + length, &response);
557		if (result != B_OK)
558			break;
559		result = info->mmc->execute_command(info->parent, info->parentCookie,
560			info->rca, SD_ERASE, kEraseModeDiscard, &response);
561		if (result != B_OK)
562			break;
563
564		trimmedSize += (info->flags & kIoCommandOffsetAsSectors) != 0
565			? length * kBlockSize : length;
566	}
567
568	trimData->trimmed_size = trimmedSize;
569
570	return result;
571}
572
573
574static status_t
575mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
576{
577	mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
578	mmc_disk_driver_info* info = handle->info;
579
580	switch (op) {
581		case B_GET_MEDIA_STATUS:
582		{
583			if (buffer == NULL || length < sizeof(status_t))
584				return B_BAD_VALUE;
585
586			*(status_t *)buffer = B_OK;
587			return B_OK;
588			break;
589		}
590
591		case B_GET_DEVICE_SIZE:
592		{
593			// Legacy ioctl, use B_GET_GEOMETRY
594			if (info->geometry.bytes_per_sector == 0) {
595				status_t error = mmc_block_get_geometry(info, &info->geometry);
596				if (error != B_OK) {
597					TRACE("Failed to get disk capacity");
598					return error;
599				}
600			}
601
602			uint64_t size = info->DeviceSize();
603			if (size > SIZE_MAX)
604				return B_NOT_SUPPORTED;
605			size_t size32 = size;
606			return user_memcpy(buffer, &size32, sizeof(size_t));
607		}
608
609		case B_GET_GEOMETRY:
610		{
611			if (buffer == NULL || length > sizeof(device_geometry))
612				return B_BAD_VALUE;
613
614			if (info->geometry.bytes_per_sector == 0) {
615				status_t error = mmc_block_get_geometry(info, &info->geometry);
616				if (error != B_OK) {
617					TRACE("Failed to get disk capacity");
618					return error;
619				}
620			}
621
622			return user_memcpy(buffer, &info->geometry, length);
623		}
624
625		case B_GET_ICON_NAME:
626			return user_strlcpy((char*)buffer, "devices/drive-harddisk",
627				B_FILE_NAME_LENGTH);
628
629		case B_GET_VECTOR_ICON:
630		{
631			// TODO: take device type into account!
632			device_icon iconData;
633			if (length != sizeof(device_icon))
634				return B_BAD_VALUE;
635			if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK)
636				return B_BAD_ADDRESS;
637
638			if (iconData.icon_size >= (int32)sizeof(kDriveIcon)) {
639				if (user_memcpy(iconData.icon_data, kDriveIcon,
640						sizeof(kDriveIcon)) != B_OK)
641					return B_BAD_ADDRESS;
642			}
643
644			iconData.icon_size = sizeof(kDriveIcon);
645			return user_memcpy(buffer, &iconData, sizeof(device_icon));
646		}
647
648		case B_TRIM_DEVICE:
649		{
650			// We know the buffer is kernel-side because it has been
651			// preprocessed in devfs
652			return mmc_block_trim(info, (fs_trim_data*)buffer);
653		}
654
655		/*case B_FLUSH_DRIVE_CACHE:
656			return synchronize_cache(info);*/
657	}
658
659	return B_DEV_INVALID_IOCTL;
660}
661
662
663module_dependency module_dependencies[] = {
664	{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
665	{}
666};
667
668
669// The "block device" associated with the device file. It can be open()
670// multiple times, eash allocating an mmc_disk_handle. It does not interact
671// with the hardware directly, instead it forwards all IO requests to the
672// disk driver through the IO scheduler.
673struct device_module_info sMMCBlockDevice = {
674	{
675		MMC_DISK_DEVICE_MODULE_NAME,
676		0,
677		NULL
678	},
679
680	mmc_block_init_device,
681	mmc_block_uninit_device,
682	NULL, // remove,
683
684	mmc_block_open,
685	mmc_block_close,
686	mmc_block_free,
687	mmc_block_read,
688	mmc_block_write,
689	mmc_block_io,
690	mmc_block_ioctl,
691
692	NULL,	// select
693	NULL,	// deselect
694};
695
696
697// Driver for the disk devices itself. This is paired with an
698// mmc_disk_driver_info instanciated once per device. Handles the actual disk
699// I/O operations
700struct driver_module_info sMMCDiskDriver = {
701	{
702		MMC_DISK_DRIVER_MODULE_NAME,
703		0,
704		NULL
705	},
706	mmc_disk_supports_device,
707	mmc_disk_register_device,
708	mmc_disk_init_driver,
709	mmc_disk_uninit_driver,
710	mmc_disk_register_child_devices,
711	NULL, // mmc_disk_rescan_child_devices,
712	NULL,
713};
714
715
716module_info* modules[] = {
717	(module_info*)&sMMCDiskDriver,
718	(module_info*)&sMMCBlockDevice,
719	NULL
720};
721