new file mode 100644
@@ -0,0 +1,45 @@
+/*
+ * SD/MMC Bus libqos
+ *
+ * Copyright (c) 2017 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef LIBQOS_SDBUS_H
+#define LIBQOS_SDBUS_H
+
+enum NCmd {
+ GO_IDLE_STATE = 0,
+ ALL_SEND_CID = 2,
+ SEND_RELATIVE_ADDR = 3,
+ SELECT_CARD = 7,
+ SEND_IF_COND = 8,
+ SEND_CSD = 9,
+};
+
+enum ACmd {
+ SEND_STATUS = 13,
+ SEND_OP_COND = 41,
+ SEND_SCR = 51,
+};
+
+typedef struct SDBusAdapter SDBusAdapter;
+struct SDBusAdapter {
+
+ ssize_t (*do_command)(SDBusAdapter *adapter, enum NCmd cmd, uint32_t arg,
+ uint8_t **response);
+ void (*write_byte)(SDBusAdapter *adapter, uint8_t value);
+ uint8_t (*read_byte)(SDBusAdapter *adapter);
+};
+
+ssize_t sdbus_do_cmd(SDBusAdapter *adapter, enum NCmd cmd, uint32_t arg,
+ uint8_t **response);
+ssize_t sdbus_do_acmd(SDBusAdapter *adapter, enum ACmd acmd, uint32_t arg,
+ uint16_t address, uint8_t **response);
+void sdbus_write_byte(SDBusAdapter *adapter, uint8_t value);
+uint8_t sdbus_read_byte(SDBusAdapter *adapter);
+
+SDBusAdapter *qmp_sdbus_create(const char *bus_name);
+
+#endif
new file mode 100644
@@ -0,0 +1,74 @@
+/*
+ * QTest SD/MMC Bus driver
+ *
+ * Copyright (c) 2017 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "libqos/sdbus.h"
+#include "libqtest.h"
+#include "qemu-common.h"
+
+static bool verbose;
+#define DPRINTF(fmt, ...) \
+ do { \
+ if (verbose) { \
+ fprintf(stderr, fmt, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
+static ssize_t do_cmd(SDBusAdapter *adapter, enum NCmd cmd, uint32_t arg,
+ uint8_t **response, bool is_app_cmd)
+{
+ const char *s_cmd = is_app_cmd ? "ACMD" : "CMD";
+ ssize_t sz;
+
+ verbose = !!getenv("V");
+ if (verbose && !is_app_cmd && (cmd == 55)) {
+ verbose = false;
+ }
+
+ DPRINTF("-> %s%02u (0x%08x)\n", s_cmd, cmd, arg);
+ sz = adapter->do_command(adapter, cmd, arg, response);
+ if (response) {
+ if (sz < 0) {
+ DPRINTF("<- %s%02u (len: %ld)\n", s_cmd, cmd, sz);
+ } else if (verbose) {
+ char *pfx = g_strdup_printf("<- %s%02u (len: %ld)", s_cmd, cmd, sz);
+
+ qemu_hexdump((const char *)*response, stderr, pfx, sz);
+ g_free(pfx);
+ }
+ } else {
+ DPRINTF("<- %s%02u\n", s_cmd, cmd);
+ }
+
+ return sz;
+}
+
+ssize_t sdbus_do_cmd(SDBusAdapter *adapter, enum NCmd cmd, uint32_t arg,
+ uint8_t **response)
+{
+ return do_cmd(adapter, cmd, arg, response, false);
+}
+
+ssize_t sdbus_do_acmd(SDBusAdapter *adapter, enum ACmd acmd, uint32_t arg,
+ uint16_t address, uint8_t **response)
+{
+ do_cmd(adapter, 55, address << 16, NULL, false);
+ // TODO check rv?
+
+ return do_cmd(adapter, acmd, arg, response, true);
+}
+
+void sdbus_write_byte(SDBusAdapter *adapter, uint8_t value)
+{
+ adapter->write_byte(adapter, value);
+}
+
+uint8_t sdbus_read_byte(SDBusAdapter *adapter)
+{
+ return adapter->read_byte(adapter);
+}
@@ -715,6 +715,7 @@ tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y)
libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
+libqos-obj-y += tests/libqos/sdbus.o
libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
libqos-spapr-obj-y += tests/libqos/rtas.o
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> --- tests/libqos/sdbus.h | 45 ++++++++++++++++++++++++++++++ tests/libqos/sdbus.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.include | 1 + 3 files changed, 120 insertions(+) create mode 100644 tests/libqos/sdbus.h create mode 100644 tests/libqos/sdbus.c