From 71e4ef764c8881d0e417540fb00f7c29106c9b49 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 07:55:06 +0000 Subject: [PATCH 1/2] Answer unknown ioctl commands quietly with -ENOTTY dmdevfs now probes every node with the standard DMDRVI_IOCTL_BLOCK_GET_INFO (0x100) and DMDRVI_IOCTL_MONITOR_GET_POLICY (0x200) commands to classify it, so dmfmc logged an "Invalid ioctl command" error for every probe. Unknown commands are not an error for a driver: return -ENOTTY without logging, as dmdrvi documents. Also move dmfmc's private commands to DMDRVI_IOCTL_CUSTOM_BASE (0x1000): they started at 1, colliding with the standard DMDRVI_IOCTL_NET_* range (0x01..), so a generic network probe would have been misread as a dmfmc command. Callers using the enum names only need a rebuild. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016sVYVjrMNmMfPjWQkkGJTM --- docs/api-reference.md | 5 +++++ include/dmfmc_types.h | 5 ++++- src/dmfmc.c | 15 +++++++++++---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/api-reference.md b/docs/api-reference.md index 6cb8209..e9feeeb 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -18,6 +18,11 @@ usable either directly or transparently through `dmdevfs`/`/dev`. ## IOCTL commands (`dmfmc_ioctl_cmd_t`) +Commands are numbered from `DMDRVI_IOCTL_CUSTOM_BASE` (0x1000) so they do not +collide with the standard `DMDRVI_IOCTL_*` commands. Any command outside this +range (e.g. the `DMDRVI_IOCTL_BLOCK_GET_INFO` / `DMDRVI_IOCTL_MONITOR_GET_POLICY` +probes sent by dmdevfs) is answered with `-ENOTTY`. + | Command | `arg` type | Meaning | |---------|-----------|---------| | `dmfmc_ioctl_cmd_get_memory_start` | `void **` | Direct pointer to the mapped memory. | diff --git a/include/dmfmc_types.h b/include/dmfmc_types.h index 78180d2..c51cffc 100644 --- a/include/dmfmc_types.h +++ b/include/dmfmc_types.h @@ -185,7 +185,10 @@ typedef enum */ typedef enum { - dmfmc_ioctl_cmd_get_memory_start = 1, /**< arg = void** - direct pointer to the mapped memory */ + /* Private commands start at DMDRVI_IOCTL_CUSTOM_BASE (0x1000, dmdrvi_ioctl.h) + * so they never collide with the standard DMDRVI_IOCTL_* commands (network, + * block, monitor) that dmdevfs and other generic clients send to any node. */ + dmfmc_ioctl_cmd_get_memory_start = 0x1000, /**< arg = void** - direct pointer to the mapped memory */ dmfmc_ioctl_cmd_get_memory_size, /**< arg = uint32_t* - size in bytes of the mapped memory */ dmfmc_ioctl_cmd_get_configured_frequency, /**< arg = uint32_t* - SDCLK frequency actually configured (Hz) */ dmfmc_ioctl_cmd_get_heap_context, /**< arg = dmheap_context_t** - heap context, or NULL if not used as heap */ diff --git a/src/dmfmc.c b/src/dmfmc.c index c5fdb25..c2b22e7 100644 --- a/src/dmfmc.c +++ b/src/dmfmc.c @@ -10,6 +10,11 @@ #include #include +#ifdef DMDRVI_IOCTL_CUSTOM_BASE +_Static_assert(dmfmc_ioctl_cmd_get_memory_start == DMDRVI_IOCTL_CUSTOM_BASE, + "dmfmc private ioctl commands must start at DMDRVI_IOCTL_CUSTOM_BASE"); +#endif + #define DMFMC_CONTEXT_MAGIC 0x444D4643 /* 'DMFC' */ /** @@ -503,10 +508,12 @@ dmod_dmdrvi_dif_api_declaration(2.0, dmfmc, int, _ioctl, ( dmdrvi_context_t cont return -EINVAL; } - if (command >= dmfmc_ioctl_cmd_max) + /* Not an error: generic clients (e.g. dmdevfs probing every node for the + * block/monitor classes) send standard DMDRVI_IOCTL_* commands the FMC + * does not implement - answer -ENOTTY quietly, as dmdrvi expects. */ + if (command < dmfmc_ioctl_cmd_get_memory_start || command >= dmfmc_ioctl_cmd_max) { - DMOD_LOG_ERROR("Invalid ioctl command %d\n", command); - return -EINVAL; + return -ENOTTY; } switch (command) @@ -555,7 +562,7 @@ dmod_dmdrvi_dif_api_declaration(2.0, dmfmc, int, _ioctl, ( dmdrvi_context_t cont return configure(context); default: - return -EINVAL; + return -ENOTTY; } } From 201cc60cd802dd078235ab65da0db103830cb2cf Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 07:57:23 +0000 Subject: [PATCH 2/2] Use DMDRVI_IOCTL_CUSTOM_BASE instead of a hard-coded 0x1000 Number the private ioctl commands from the dmdrvi_ioctl.h constant itself rather than repeating its value, so they follow dmdrvi if the base ever moves. This makes the public header include dmdrvi_ioctl.h, so every in-repo target that includes it now also pulls in the dmdrvi module headers. The _Static_assert that guarded the copied value is no longer needed. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016sVYVjrMNmMfPjWQkkGJTM --- docs/api-reference.md | 2 +- include/dmfmc_types.h | 5 +++-- src/dmfmc.c | 5 ----- src/port/CMakeLists.txt | 2 ++ 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/api-reference.md b/docs/api-reference.md index e9feeeb..4a830e2 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -18,7 +18,7 @@ usable either directly or transparently through `dmdevfs`/`/dev`. ## IOCTL commands (`dmfmc_ioctl_cmd_t`) -Commands are numbered from `DMDRVI_IOCTL_CUSTOM_BASE` (0x1000) so they do not +Commands are numbered from `DMDRVI_IOCTL_CUSTOM_BASE` so they do not collide with the standard `DMDRVI_IOCTL_*` commands. Any command outside this range (e.g. the `DMDRVI_IOCTL_BLOCK_GET_INFO` / `DMDRVI_IOCTL_MONITOR_GET_POLICY` probes sent by dmdevfs) is answered with `-ENOTTY`. diff --git a/include/dmfmc_types.h b/include/dmfmc_types.h index c51cffc..f5e6da4 100644 --- a/include/dmfmc_types.h +++ b/include/dmfmc_types.h @@ -2,6 +2,7 @@ #define DMFMC_TYPES_H #include +#include "dmdrvi_ioctl.h" #include #include @@ -185,10 +186,10 @@ typedef enum */ typedef enum { - /* Private commands start at DMDRVI_IOCTL_CUSTOM_BASE (0x1000, dmdrvi_ioctl.h) + /* Private commands start at DMDRVI_IOCTL_CUSTOM_BASE (dmdrvi_ioctl.h) * so they never collide with the standard DMDRVI_IOCTL_* commands (network, * block, monitor) that dmdevfs and other generic clients send to any node. */ - dmfmc_ioctl_cmd_get_memory_start = 0x1000, /**< arg = void** - direct pointer to the mapped memory */ + dmfmc_ioctl_cmd_get_memory_start = DMDRVI_IOCTL_CUSTOM_BASE, /**< arg = void** - direct pointer to the mapped memory */ dmfmc_ioctl_cmd_get_memory_size, /**< arg = uint32_t* - size in bytes of the mapped memory */ dmfmc_ioctl_cmd_get_configured_frequency, /**< arg = uint32_t* - SDCLK frequency actually configured (Hz) */ dmfmc_ioctl_cmd_get_heap_context, /**< arg = dmheap_context_t** - heap context, or NULL if not used as heap */ diff --git a/src/dmfmc.c b/src/dmfmc.c index c2b22e7..3d656a2 100644 --- a/src/dmfmc.c +++ b/src/dmfmc.c @@ -10,11 +10,6 @@ #include #include -#ifdef DMDRVI_IOCTL_CUSTOM_BASE -_Static_assert(dmfmc_ioctl_cmd_get_memory_start == DMDRVI_IOCTL_CUSTOM_BASE, - "dmfmc private ioctl commands must start at DMDRVI_IOCTL_CUSTOM_BASE"); -#endif - #define DMFMC_CONTEXT_MAGIC 0x444D4643 /* 'DMFC' */ /** diff --git a/src/port/CMakeLists.txt b/src/port/CMakeLists.txt index 671c696..f9dcdff 100644 --- a/src/port/CMakeLists.txt +++ b/src/port/CMakeLists.txt @@ -38,8 +38,10 @@ dmod_add_library(${DMOD_MODULE_NAME} ${DMOD_MODULE_VERSION} ${COMMON_SOURCES} ) +# dmdrvi: dmfmc_types.h pulls in dmdrvi_ioctl.h (DMDRVI_IOCTL_CUSTOM_BASE) dmod_link_modules(${DMOD_MODULE_NAME} dmclk_port + dmdrvi ) target_include_directories(${DMOD_MODULE_NAME} BEFORE PRIVATE