1 /* 2 * Copyright 2018-2020 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 <string.h> 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <ctype.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 27 // #include <fs/devfs.h> 28 29 #define TRACE_MMC_DISK 30 #ifdef TRACE_MMC_DISK 31 # define TRACE(x...) dprintf("\33[33mmmc_disk:\33[0m " x) 32 #else 33 # define TRACE(x...) ; 34 #endif 35 #define ERROR(x...) dprintf("\33[33mmmc_disk:\33[0m " x) 36 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 37 38 #define MMC_DISK_DRIVER_MODULE_NAME "drivers/disk/mmc/mmc_disk/driver_v1" 39 #define MMC_DISK_DEVICE_MODULE_NAME "drivers/disk/mmc/mmc_disk/device_v1" 40 #define MMC_DEVICE_ID_GENERATOR "mmc/device_id" 41 42 static device_manager_info* sDeviceManager; 43 44 45 struct mmc_disk_csd { 46 uint64 bits[2]; 47 48 uint8 structure_version() { return bits[1] >> 60; } 49 uint8 read_bl_len() { return (bits[1] >> 8) & 0xF; } 50 uint16 c_size() 51 { 52 return ((bits[0] >> 54) & 0x3FF) | ((bits[1] & 0x3) << 10); 53 } 54 uint8 c_size_mult() { return (bits[0] >> 39) & 0x7; } 55 }; 56 57 58 static float 59 mmc_disk_supports_device(device_node* parent) 60 { 61 // Filter all devices that are not on an MMC bus 62 const char* bus; 63 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, 64 true) != B_OK) 65 return -1; 66 67 if (strcmp(bus, "mmc") != 0) 68 return 0.0; 69 70 CALLED(); 71 72 // Filter all devices that are not of the known types 73 uint8_t deviceType; 74 if (sDeviceManager->get_attr_uint8(parent, kMmcTypeAttribute, 75 &deviceType, true) != B_OK) 76 { 77 ERROR("Could not get device type\n"); 78 return -1; 79 } 80 81 if (deviceType == CARD_TYPE_SD) 82 TRACE("SD card found, parent: %p\n", parent); 83 else if (deviceType == CARD_TYPE_SDHC) 84 TRACE("SDHC card found, parent: %p\n", parent); 85 else 86 return 0.0; 87 88 return 0.8; 89 } 90 91 92 static status_t 93 mmc_disk_register_device(device_node* node) 94 { 95 CALLED(); 96 97 device_attr attrs[] = { 98 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "SD Card" }}, 99 { NULL } 100 }; 101 102 return sDeviceManager->register_node(node 103 , MMC_DISK_DRIVER_MODULE_NAME, attrs, NULL, NULL); 104 } 105 106 107 static status_t 108 mmc_disk_init_driver(device_node* node, void** cookie) 109 { 110 CALLED(); 111 mmc_disk_driver_info* info = (mmc_disk_driver_info*)malloc( 112 sizeof(mmc_disk_driver_info)); 113 114 if (info == NULL) 115 return B_NO_MEMORY; 116 117 memset(info, 0, sizeof(*info)); 118 119 void* unused; 120 info->node = node; 121 info->parent = sDeviceManager->get_parent_node(info->node); 122 sDeviceManager->get_driver(info->parent, (driver_module_info **)&info->mmc, 123 &unused); 124 125 TRACE("MMC bus handle: %p %s\n", info->mmc, info->mmc->info.info.name); 126 127 if (sDeviceManager->get_attr_uint16(node, kMmcRcaAttribute, &info->rca, 128 true) != B_OK) { 129 TRACE("MMC card node has no RCA attribute\n"); 130 free(info); 131 return B_BAD_DATA; 132 } 133 134 TRACE("MMC card device initialized for RCA %x\n", info->rca); 135 136 *cookie = info; 137 return B_OK; 138 } 139 140 141 static void 142 mmc_disk_uninit_driver(void* _cookie) 143 { 144 CALLED(); 145 mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie; 146 sDeviceManager->put_node(info->parent); 147 free(info); 148 } 149 150 151 static status_t 152 mmc_disk_register_child_devices(void* _cookie) 153 { 154 CALLED(); 155 mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie; 156 status_t status; 157 158 int32 id = sDeviceManager->create_id(MMC_DEVICE_ID_GENERATOR); 159 if (id < 0) 160 return id; 161 162 char name[64]; 163 snprintf(name, sizeof(name), "disk/mmc/%" B_PRId32 "/raw", id); 164 165 status = sDeviceManager->publish_device(info->node, name, 166 MMC_DISK_DEVICE_MODULE_NAME); 167 168 return status; 169 } 170 171 172 // #pragma mark - device module API 173 174 175 static status_t 176 mmc_block_init_device(void* _info, void** _cookie) 177 { 178 CALLED(); 179 180 // No additional context, so just reuse the same data as the disk device 181 mmc_disk_driver_info* info = (mmc_disk_driver_info*)_info; 182 *_cookie = info; 183 184 return B_OK; 185 } 186 187 188 static void 189 mmc_block_uninit_device(void* _cookie) 190 { 191 CALLED(); 192 //mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie; 193 194 // TODO cleanup whatever is relevant 195 } 196 197 198 static status_t 199 mmc_block_open(void* _info, const char* path, int openMode, void** _cookie) 200 { 201 CALLED(); 202 mmc_disk_driver_info* info = (mmc_disk_driver_info*)_info; 203 204 // allocate cookie 205 mmc_disk_handle* handle = new(std::nothrow) mmc_disk_handle; 206 *_cookie = handle; 207 if (handle == NULL) { 208 return B_NO_MEMORY; 209 } 210 handle->info = info; 211 212 return B_OK; 213 } 214 215 216 static status_t 217 mmc_block_close(void* cookie) 218 { 219 mmc_disk_handle* handle = (mmc_disk_handle*)cookie; 220 CALLED(); 221 222 return B_OK; 223 } 224 225 226 static status_t 227 mmc_block_free(void* cookie) 228 { 229 CALLED(); 230 mmc_disk_handle* handle = (mmc_disk_handle*)cookie; 231 232 delete handle; 233 return B_OK; 234 } 235 236 237 static status_t 238 mmc_block_read(void* cookie, off_t pos, void* buffer, size_t* _length) 239 { 240 CALLED(); 241 mmc_disk_handle* handle = (mmc_disk_handle*)cookie; 242 TRACE("Ready to execute %p\n", handle->info->mmc->read_naive); 243 return handle->info->mmc->read_naive(handle->info->parent, handle->info->rca, pos, buffer, _length); 244 } 245 246 247 static status_t 248 mmc_block_write(void* cookie, off_t position, const void* buffer, 249 size_t* length) 250 { 251 CALLED(); 252 mmc_disk_handle* handle = (mmc_disk_handle*)cookie; 253 254 return B_NOT_SUPPORTED; 255 } 256 257 258 static status_t 259 mmc_block_io(void* cookie, io_request* request) 260 { 261 CALLED(); 262 mmc_disk_handle* handle = (mmc_disk_handle*)cookie; 263 264 return B_NOT_SUPPORTED; 265 } 266 267 268 static status_t 269 mmc_block_get_geometry(mmc_disk_handle* handle, device_geometry* geometry) 270 { 271 struct mmc_disk_csd csd; 272 TRACE("Ready to execute %p\n", handle->info->mmc->execute_command); 273 handle->info->mmc->execute_command(handle->info->parent, SD_SEND_CSD, 274 handle->info->rca << 16, (uint32_t*)&csd); 275 276 TRACE("CSD: %lx %lx\n", csd.bits[0], csd.bits[1]); 277 278 if (csd.structure_version() == 0) { 279 geometry->bytes_per_sector = 1 << csd.read_bl_len(); 280 geometry->sectors_per_track = csd.c_size() + 1; 281 geometry->cylinder_count = 1 << (csd.c_size_mult() + 2); 282 geometry->head_count = 1; 283 geometry->device_type = B_DISK; 284 geometry->removable = true; // TODO detect eMMC which isn't 285 geometry->read_only = true; // TODO add write support 286 geometry->write_once = false; 287 return B_OK; 288 } 289 290 TRACE("unknown CSD version %d\n", csd.structure_version()); 291 return B_NOT_SUPPORTED; 292 } 293 294 295 static status_t 296 mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) 297 { 298 CALLED(); 299 mmc_disk_handle* handle = (mmc_disk_handle*)cookie; 300 mmc_disk_driver_info* info = handle->info; 301 302 TRACE("ioctl(op = %" B_PRId32 ")\n", op); 303 304 switch (op) { 305 case B_GET_MEDIA_STATUS: 306 { 307 if (buffer == NULL || length < sizeof(status_t)) 308 return B_BAD_VALUE; 309 310 *(status_t *)buffer = B_OK; 311 TRACE("B_GET_MEDIA_STATUS: 0x%08" B_PRIx32 "\n", 312 *(status_t *)buffer); 313 return B_OK; 314 break; 315 } 316 317 case B_GET_DEVICE_SIZE: 318 { 319 //size_t size = info->capacity * info->block_size; 320 //return user_memcpy(buffer, &size, sizeof(size_t)); 321 return B_NOT_SUPPORTED; 322 } 323 324 case B_GET_GEOMETRY: 325 { 326 if (buffer == NULL || length < sizeof(device_geometry)) 327 return B_BAD_VALUE; 328 329 device_geometry geometry; 330 status_t status = mmc_block_get_geometry(handle, &geometry); 331 if (status != B_OK) 332 return status; 333 334 return user_memcpy(buffer, &geometry, sizeof(device_geometry)); 335 } 336 337 case B_GET_ICON_NAME: 338 return user_strlcpy((char*)buffer, "devices/drive-harddisk", 339 B_FILE_NAME_LENGTH); 340 341 case B_GET_VECTOR_ICON: 342 { 343 // TODO: take device type into account! 344 device_icon iconData; 345 if (length != sizeof(device_icon)) 346 return B_BAD_VALUE; 347 if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK) 348 return B_BAD_ADDRESS; 349 350 if (iconData.icon_size >= (int32)sizeof(kDriveIcon)) { 351 if (user_memcpy(iconData.icon_data, kDriveIcon, 352 sizeof(kDriveIcon)) != B_OK) 353 return B_BAD_ADDRESS; 354 } 355 356 iconData.icon_size = sizeof(kDriveIcon); 357 return user_memcpy(buffer, &iconData, sizeof(device_icon)); 358 } 359 360 /*case B_FLUSH_DRIVE_CACHE: 361 return synchronize_cache(info);*/ 362 } 363 364 return B_DEV_INVALID_IOCTL; 365 } 366 367 368 module_dependency module_dependencies[] = { 369 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager}, 370 {} 371 }; 372 373 374 // The "block device" associated with the device file. It can be open() 375 // multiple times, eash allocating an mmc_disk_handle. It does not interact 376 // with the hardware directly, instead it forwards all IO requests to the 377 // disk driver through the IO scheduler. 378 struct device_module_info sMMCBlockDevice = { 379 { 380 MMC_DISK_DEVICE_MODULE_NAME, 381 0, 382 NULL 383 }, 384 385 mmc_block_init_device, 386 mmc_block_uninit_device, 387 NULL, // remove, 388 389 mmc_block_open, 390 mmc_block_close, 391 mmc_block_free, 392 mmc_block_read, 393 mmc_block_write, 394 mmc_block_io, 395 mmc_block_ioctl, 396 397 NULL, // select 398 NULL, // deselect 399 }; 400 401 402 // Driver for the disk devices itself. This is paired with an 403 // mmc_disk_driver_info instanciated once per device. Handles the actual disk 404 // I/O operations 405 struct driver_module_info sMMCDiskDriver = { 406 { 407 MMC_DISK_DRIVER_MODULE_NAME, 408 0, 409 NULL 410 }, 411 mmc_disk_supports_device, 412 mmc_disk_register_device, 413 mmc_disk_init_driver, 414 mmc_disk_uninit_driver, 415 mmc_disk_register_child_devices, 416 NULL, // mmc_disk_rescan_child_devices, 417 NULL, 418 }; 419 420 421 module_info* modules[] = { 422 (module_info*)&sMMCDiskDriver, 423 (module_info*)&sMMCBlockDevice, 424 NULL 425 }; 426