[haiku-commits] Change in haiku[master]: mmc_disk: implement get_capacity

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 25 Jul 2020 20:33:57 +0000

From Adrien Destugues <pulkomandy@xxxxxxxxx>:

Adrien Destugues has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/3091 ;)


Change subject: mmc_disk: implement get_capacity
......................................................................

mmc_disk: implement get_capacity

Only for SD cards for now. SDHC uses a different layout for the CSD
register (and will be rejected as invalid here).
---
M headers/private/drivers/mmc.h
M src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
M src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
3 files changed, 85 insertions(+), 21 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/91/3091/1

diff --git a/headers/private/drivers/mmc.h b/headers/private/drivers/mmc.h
index 8638e5f..96dd78b 100644
--- a/headers/private/drivers/mmc.h
+++ b/headers/private/drivers/mmc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019, Haiku, Inc. All Rights Reserved.
+ * Copyright 2019-2020, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
@@ -25,7 +25,8 @@
 };


-// Interface between mmc_bus and underlying implementation
+// Interface between mmc_bus and underlying implementation (sdhci_pci or any
+// other thing that can execute mmc commands)
 typedef struct mmc_bus_interface {
        driver_module_info info;

@@ -35,4 +36,13 @@
 } mmc_bus_interface;


+// Interface between mmc device driver (mmc_disk, sdio drivers, ...) and 
mmc_bus
+typedef struct mmc_device_interface {
+       driver_module_info info;
+
+       status_t (*execute_command)(uint8_t command,
+               uint32_t argument, uint32_t* result);
+} mmc_device_interface;
+
+
 #endif /* _MMC_H */
diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp 
b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
index 011ca77..8c12f48 100644
--- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
@@ -41,6 +41,16 @@
 static device_manager_info* sDeviceManager;


+struct mmc_disk_csd {
+       uint64 bits[2];
+
+       uint8_t structure_version() { return bits[1] >> 60; }
+       uint8_t read_bl_len() { return (bits[1] >> 8) & 0xF; }
+       uint16_t c_size() { return ((bits[0] >> 54) & 0x3FF) | ((bits[1] & 0x3) 
<< 10); }
+       uint8_t c_size_mult() { return (bits[0] >> 39) & 0x7; }
+};
+
+
 static float
 mmc_disk_supports_device(device_node* parent)
 {
@@ -102,6 +112,32 @@

        info->node = node;

+       device_node* parent = sDeviceManager->get_parent_node(info->node);
+       // FIXME we get directly to the sdhci driver here. Instead, mmc_bus 
should
+       // provide a way to send commands (and forward them to the sdhci 
device).
+       // Also there are way too many intermediate nodes...
+       device_node* grandparent = sDeviceManager->get_parent_node(parent);
+       device_node* grandgrandparent = 
sDeviceManager->get_parent_node(grandparent);
+       sDeviceManager->get_driver(grandgrandparent, (driver_module_info 
**)&info->mmc,
+               &info->mmc_device);
+       sDeviceManager->put_node(grandgrandparent);
+       sDeviceManager->put_node(grandparent);
+       sDeviceManager->put_node(parent);
+
+       if (info->mmc == NULL || info->mmc_device == NULL) {
+               panic("Failed to get MMC bus handles %p %s %p", info->mmc,
+                       info->mmc->info.info.name, info->mmc_device);
+       }
+
+       if (sDeviceManager->get_attr_uint16(node, "mmc/rca", &info->rca, true)
+               != B_OK) {
+               TRACE("MMC card node has no RCA attribute\n");
+               free(info);
+               return B_BAD_DATA;
+       }
+
+       TRACE("MMC card device initialized for RCA %x\n", info->rca);
+
        *cookie = info;
        return B_OK;
 }
@@ -144,17 +180,12 @@
 mmc_block_init_device(void* _info, void** _cookie)
 {
        CALLED();
+
+       // No additional context, so just reuse the same data as the disk device
        mmc_disk_driver_info* info = (mmc_disk_driver_info*)_info;
+       *_cookie = info;

-       device_node* parent = sDeviceManager->get_parent_node(info->node);
-       sDeviceManager->get_driver(parent, (driver_module_info **)&info->mmc,
-               (void **)&info->mmc_device);
-       sDeviceManager->put_node(parent);
-
-       status_t status = B_OK;
-       // TODO Get capacity
-
-       return status;
+       return B_OK;
 }


@@ -208,6 +239,32 @@


 static status_t
+mmc_block_get_geometry(mmc_disk_handle* handle, device_geometry* geometry)
+{
+       struct mmc_disk_csd csd;
+       handle->info->mmc->execute_command(handle->info->mmc_device, 9,
+               handle->info->rca << 16, (uint32_t*)&csd);
+
+       TRACE("CSD: %lx %lx\n", csd.bits[0], csd.bits[1]);
+
+       if (csd.structure_version() == 0) {
+               geometry->bytes_per_sector = 1 << csd.read_bl_len();
+               geometry->sectors_per_track = csd.c_size() + 1;
+               geometry->cylinder_count = 1 << (csd.c_size_mult() + 2);
+               geometry->head_count = 1;
+               geometry->device_type = B_DISK;
+               geometry->removable = true; // TODO detect eMMC which isn't
+               geometry->read_only = true; // TODO add write support
+               geometry->write_once = false;
+               return B_OK;
+       }
+
+       TRACE("unknown CSD version %d\n", csd.structure_version());
+       return B_NOT_SUPPORTED;
+}
+
+
+static status_t
 mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
 {
        CALLED();
@@ -230,8 +287,9 @@

                case B_GET_DEVICE_SIZE:
                {
-                       size_t size = info->capacity * info->block_size;
-                       return user_memcpy(buffer, &size, sizeof(size_t));
+                       //size_t size = info->capacity * info->block_size;
+                       //return user_memcpy(buffer, &size, sizeof(size_t));
+                       return B_NOT_SUPPORTED;
                }

                case B_GET_GEOMETRY:
@@ -240,8 +298,7 @@
                                return B_BAD_VALUE;

                        device_geometry geometry;
-                       // TODO status_t status = get_geometry(handle, 
&geometry);
-                       status_t status = B_ERROR;
+                       status_t status = mmc_block_get_geometry(handle, 
&geometry);
                        if (status != B_OK)
                                return status;

diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h 
b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
index 621f1f7..5962d28 100644
--- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
+++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
@@ -15,16 +15,13 @@

 #include <stdint.h>

-typedef struct {
-       driver_module_info stdops;
-
-       // TODO specific ops provided by MMC bus go here (for sending commands, 
etc)
-} mmc_driver_interface;
+#include <mmc.h>

 typedef struct {
        device_node*    node;
-       mmc_driver_interface* mmc;
+       mmc_bus_interface* mmc;
        void* mmc_device;
+       uint16_t rca;

        size_t block_size;
        uint32_t capacity;

--
To view, visit https://review.haiku-os.org/c/haiku/+/3091
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I263c4f2d78ff87d6a3ab7a48ecea8f8b3b2f6309
Gerrit-Change-Number: 3091
Gerrit-PatchSet: 1
Gerrit-Owner: Adrien Destugues <pulkomandy@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: mmc_disk: implement get_capacity - Gerrit