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