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
45 static const uint32 kBlockSize = 512; // FIXME get it from the CSD
46
47 static device_manager_info* sDeviceManager;
48
49
50 struct 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
structure_versionmmc_disk_csd55 uint8 structure_version() { return bits[1] >> 54; }
read_bl_lenmmc_disk_csd56 uint8 read_bl_len() { return (bits[1] >> 8) & 0xF; }
c_sizemmc_disk_csd57 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
c_size_multmmc_disk_csd66 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
77 static float
mmc_disk_supports_device(device_node * parent)78 mmc_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
111 static status_t
mmc_disk_register_device(device_node * node)112 mmc_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
126 static status_t
mmc_disk_execute_iorequest(void * data,IOOperation * operation)127 mmc_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
150 static status_t
mmc_block_get_geometry(mmc_disk_driver_info * info,device_geometry * geometry)151 mmc_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
195 static status_t
mmc_disk_init_driver(device_node * node,void ** cookie)196 mmc_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
292 static void
mmc_disk_uninit_driver(void * _cookie)293 mmc_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
304 static status_t
mmc_disk_register_child_devices(void * _cookie)305 mmc_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
328 static status_t
mmc_block_init_device(void * _info,void ** _cookie)329 mmc_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
344 static void
mmc_block_uninit_device(void * _cookie)345 mmc_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
354 static status_t
mmc_block_open(void * _info,const char * path,int openMode,void ** _cookie)355 mmc_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 if (handle->info->geometry.bytes_per_sector == 0) {
369 status_t error = mmc_block_get_geometry(handle->info,
370 &handle->info->geometry);
371 if (error != B_OK) {
372 TRACE("Failed to get disk capacity");
373 delete handle;
374 *_cookie = NULL;
375 return error;
376 }
377 }
378
379 return B_OK;
380 }
381
382
383 static status_t
mmc_block_close(void * cookie)384 mmc_block_close(void* cookie)
385 {
386 //mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
387 CALLED();
388
389 return B_OK;
390 }
391
392
393 static status_t
mmc_block_free(void * cookie)394 mmc_block_free(void* cookie)
395 {
396 CALLED();
397 mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
398
399 delete handle;
400 return B_OK;
401 }
402
403
404 static status_t
mmc_block_read(void * cookie,off_t position,void * buffer,size_t * _length)405 mmc_block_read(void* cookie, off_t position, void* buffer, size_t* _length)
406 {
407 CALLED();
408 mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
409
410 size_t length = *_length;
411 if (position >= handle->info->DeviceSize())
412 return ERANGE;
413 if ((position + (off_t)length) > handle->info->DeviceSize())
414 length = (handle->info->DeviceSize() - position);
415
416 IORequest request;
417 status_t status = request.Init(position, (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 *_length = request.TransferredBytes();
427 return status;
428 }
429
430
431 static status_t
mmc_block_write(void * cookie,off_t position,const void * buffer,size_t * _length)432 mmc_block_write(void* cookie, off_t position, const void* buffer,
433 size_t* _length)
434 {
435 CALLED();
436 mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
437
438 size_t length = *_length;
439 if (position >= handle->info->DeviceSize())
440 return ERANGE;
441 if ((position + (off_t)length) > handle->info->DeviceSize())
442 length = (handle->info->DeviceSize() - position);
443
444 IORequest request;
445 status_t status = request.Init(position, (addr_t)buffer, length, true, 0);
446 if (status != B_OK)
447 return status;
448
449 status = handle->info->scheduler->ScheduleRequest(&request);
450 if (status != B_OK)
451 return status;
452
453 status = request.Wait(0, 0);
454 *_length = request.TransferredBytes();
455 return status;
456 }
457
458
459 static status_t
mmc_block_io(void * cookie,io_request * request)460 mmc_block_io(void* cookie, io_request* request)
461 {
462 CALLED();
463 mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
464
465 if ((request->Offset() + (off_t)request->Length()) > handle->info->DeviceSize())
466 return ERANGE;
467
468 return handle->info->scheduler->ScheduleRequest(request);
469 }
470
471
472 static status_t
mmc_block_trim(mmc_disk_driver_info * info,fs_trim_data * trimData)473 mmc_block_trim(mmc_disk_driver_info* info, fs_trim_data* trimData)
474 {
475 enum {
476 kEraseModeErase = 0, // force to actually erase the data
477 kEraseModeDiscard = 1,
478 // just mark the data as unused for internal wear leveling
479 // algorithms
480 kEraseModeFullErase = 2, // erase the whole card
481 };
482 TRACE("trim_device()\n");
483
484 trimData->trimmed_size = 0;
485
486 const off_t deviceSize = info->DeviceSize(); // in bytes
487 if (deviceSize < 0)
488 return B_BAD_VALUE;
489
490 STATIC_ASSERT(sizeof(deviceSize) <= sizeof(uint64));
491 ASSERT(deviceSize >= 0);
492
493 // Do not trim past device end
494 for (uint32 i = 0; i < trimData->range_count; i++) {
495 uint64 offset = trimData->ranges[i].offset;
496 uint64& size = trimData->ranges[i].size;
497
498 if (offset >= (uint64)deviceSize)
499 return B_BAD_VALUE;
500 size = min_c(size, (uint64)deviceSize - offset);
501 }
502
503 uint64 trimmedSize = 0;
504 status_t result = B_OK;
505 for (uint32 i = 0; i < trimData->range_count; i++) {
506 uint64 offset = trimData->ranges[i].offset;
507 uint64 length = trimData->ranges[i].size;
508
509 // Round up offset and length to multiple of the sector size
510 // The offset is rounded up, so some space may be left
511 // (not trimmed) at the start of the range.
512 offset = ROUNDUP(offset, kBlockSize);
513 // Adjust the length for the possibly skipped range
514 length -= offset - trimData->ranges[i].offset;
515 // The length is rounded down, so some space at the end may also
516 // be left (not trimmed).
517 length &= ~(kBlockSize - 1);
518
519 if (length == 0)
520 continue;
521
522 TRACE("trim %" B_PRIu64 " bytes from %" B_PRIu64 "\n",
523 length, offset);
524
525 ASSERT(offset % kBlockSize == 0);
526 ASSERT(length % kBlockSize == 0);
527
528 if ((info->flags & kIoCommandOffsetAsSectors) != 0) {
529 offset /= kBlockSize;
530 length /= kBlockSize;
531 }
532
533 // Parameter of execute_command is uint32_t
534 if (offset > UINT32_MAX
535 || length > UINT32_MAX - offset) {
536 result = B_BAD_VALUE;
537 break;
538 }
539
540 uint32_t response;
541 result = info->mmc->execute_command(info->parent, info->parentCookie,
542 info->rca, SD_ERASE_WR_BLK_START, offset, &response);
543 if (result != B_OK)
544 break;
545 result = info->mmc->execute_command(info->parent, info->parentCookie,
546 info->rca, SD_ERASE_WR_BLK_END, offset + length, &response);
547 if (result != B_OK)
548 break;
549 result = info->mmc->execute_command(info->parent, info->parentCookie,
550 info->rca, SD_ERASE, kEraseModeDiscard, &response);
551 if (result != B_OK)
552 break;
553
554 trimmedSize += (info->flags & kIoCommandOffsetAsSectors) != 0
555 ? length * kBlockSize : length;
556 }
557
558 trimData->trimmed_size = trimmedSize;
559
560 return result;
561 }
562
563
564 static status_t
mmc_block_ioctl(void * cookie,uint32 op,void * buffer,size_t length)565 mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
566 {
567 mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
568 mmc_disk_driver_info* info = handle->info;
569
570 switch (op) {
571 case B_GET_MEDIA_STATUS:
572 {
573 if (buffer == NULL || length < sizeof(status_t))
574 return B_BAD_VALUE;
575
576 status_t status = B_OK;
577 return user_memcpy(buffer, &status, sizeof(status_t));
578 }
579
580 case B_GET_DEVICE_SIZE:
581 {
582 // Legacy ioctl, use B_GET_GEOMETRY
583
584 uint64_t size = info->DeviceSize();
585 if (size > SIZE_MAX)
586 return B_NOT_SUPPORTED;
587 size_t size32 = size;
588 return user_memcpy(buffer, &size32, sizeof(size_t));
589 }
590
591 case B_GET_GEOMETRY:
592 {
593 if (buffer == NULL || length > sizeof(device_geometry))
594 return B_BAD_VALUE;
595
596 return user_memcpy(buffer, &info->geometry, length);
597 }
598
599 case B_GET_ICON_NAME:
600 return user_strlcpy((char*)buffer, "devices/drive-harddisk",
601 B_FILE_NAME_LENGTH);
602
603 case B_GET_VECTOR_ICON:
604 {
605 // TODO: take device type into account!
606 device_icon iconData;
607 if (length != sizeof(device_icon))
608 return B_BAD_VALUE;
609 if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK)
610 return B_BAD_ADDRESS;
611
612 if (iconData.icon_size >= (int32)sizeof(kDriveIcon)) {
613 if (user_memcpy(iconData.icon_data, kDriveIcon,
614 sizeof(kDriveIcon)) != B_OK)
615 return B_BAD_ADDRESS;
616 }
617
618 iconData.icon_size = sizeof(kDriveIcon);
619 return user_memcpy(buffer, &iconData, sizeof(device_icon));
620 }
621
622 case B_TRIM_DEVICE:
623 {
624 // We know the buffer is kernel-side because it has been
625 // preprocessed in devfs
626 return mmc_block_trim(info, (fs_trim_data*)buffer);
627 }
628
629 /*case B_FLUSH_DRIVE_CACHE:
630 return synchronize_cache(info);*/
631 }
632
633 return B_DEV_INVALID_IOCTL;
634 }
635
636
637 module_dependency module_dependencies[] = {
638 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
639 {}
640 };
641
642
643 // The "block device" associated with the device file. It can be open()
644 // multiple times, eash allocating an mmc_disk_handle. It does not interact
645 // with the hardware directly, instead it forwards all IO requests to the
646 // disk driver through the IO scheduler.
647 struct device_module_info sMMCBlockDevice = {
648 {
649 MMC_DISK_DEVICE_MODULE_NAME,
650 0,
651 NULL
652 },
653
654 mmc_block_init_device,
655 mmc_block_uninit_device,
656 NULL, // remove,
657
658 mmc_block_open,
659 mmc_block_close,
660 mmc_block_free,
661 mmc_block_read,
662 mmc_block_write,
663 mmc_block_io,
664 mmc_block_ioctl,
665
666 NULL, // select
667 NULL, // deselect
668 };
669
670
671 // Driver for the disk devices itself. This is paired with an
672 // mmc_disk_driver_info instanciated once per device. Handles the actual disk
673 // I/O operations
674 struct driver_module_info sMMCDiskDriver = {
675 {
676 MMC_DISK_DRIVER_MODULE_NAME,
677 0,
678 NULL
679 },
680 mmc_disk_supports_device,
681 mmc_disk_register_device,
682 mmc_disk_init_driver,
683 mmc_disk_uninit_driver,
684 mmc_disk_register_child_devices,
685 NULL, // mmc_disk_rescan_child_devices,
686 NULL,
687 };
688
689
690 module_info* modules[] = {
691 (module_info*)&sMMCDiskDriver,
692 (module_info*)&sMMCBlockDevice,
693 NULL
694 };
695