diff --git a/zircon/system/banjo/ddk.protocol.sdio/sdio.banjo b/zircon/system/banjo/ddk.protocol.sdio/sdio.banjo
index 900bcd8bb54c387bedb50273564667ee3395740f..7c9ae4ca0ef6ddc67efd6f7dfdbb410b65c4c4cd 100644
--- a/zircon/system/banjo/ddk.protocol.sdio/sdio.banjo
+++ b/zircon/system/banjo/ddk.protocol.sdio/sdio.banjo
@@ -81,4 +81,11 @@ protocol Sdio {
     DoRwTxn(uint8 fn_idx, SdioRwTxn? txn) -> (zx.status s);
     DoRwByte(bool write, uint8 fn_idx, uint32 addr, uint8 write_byte) -> (zx.status s, uint8 read_byte);
     GetInBandIntr(uint8 fn_idx) -> (zx.status s, handle<interrupt> irq);
+    /// The following functions access the card common control registers (CCCR) on function 0.
+    /// Aborts an I/O operation occurring on the specified function.
+    IoAbort(uint8 fn_idx) -> (zx.status s);
+    /// Returns true if an interrupt is pending for function fn_idx, false otherwise.
+    IntrPending(uint8 fn_idx) -> (zx.status s, bool pending);
+    /// Reads or writes to a vendor CCCR register. addr must be in [0xF0, 0xFF].
+    DoVendorControlRwByte(bool write, uint8 addr, uint8 write_byte) -> (zx.status s, uint8 read_byte);
 };
diff --git a/zircon/system/dev/block/sdmmc/sdio-controller-device-test.cpp b/zircon/system/dev/block/sdmmc/sdio-controller-device-test.cpp
index 1b44a756b7d23f0db2f65728bd94cb937bd6694c..6522e453c80576d601a1b97abdb5ad0b1f039b5c 100644
--- a/zircon/system/dev/block/sdmmc/sdio-controller-device-test.cpp
+++ b/zircon/system/dev/block/sdmmc/sdio-controller-device-test.cpp
@@ -329,4 +329,41 @@ TEST(SdioControllerDeviceTest, DdkLifecycle) {
     EXPECT_EQ(ddk.total_children(), 4);
 }
 
+TEST(SdioControllerDeviceTest, SdioIntrPending) {
+    MockSdmmcDevice mock_sdmmc({});
+    SdioControllerDeviceTest dut(&mock_sdmmc, {});
+
+    dut.mock_SdioDoRwByte()
+        .ExpectCall({ZX_OK, 0b0011'0010}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0)
+        .ExpectCall({ZX_OK, 0b0010'0010}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0)
+        .ExpectCall({ZX_OK, 0b1000'0000}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0)
+        .ExpectCall({ZX_OK, 0b0000'0000}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0)
+        .ExpectCall({ZX_OK, 0b0000'1110}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0)
+        .ExpectCall({ZX_OK, 0b0000'1110}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0)
+        .ExpectCall({ZX_OK, 0b0000'1110}, false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0);
+
+    bool pending;
+
+    EXPECT_OK(dut.SdioIntrPending(4, &pending));
+    EXPECT_TRUE(pending);
+
+    EXPECT_OK(dut.SdioIntrPending(4, &pending));
+    EXPECT_FALSE(pending);
+
+    EXPECT_OK(dut.SdioIntrPending(7, &pending));
+    EXPECT_TRUE(pending);
+
+    EXPECT_OK(dut.SdioIntrPending(7, &pending));
+    EXPECT_FALSE(pending);
+
+    EXPECT_OK(dut.SdioIntrPending(1, &pending));
+    EXPECT_TRUE(pending);
+
+    EXPECT_OK(dut.SdioIntrPending(2, &pending));
+    EXPECT_TRUE(pending);
+
+    EXPECT_OK(dut.SdioIntrPending(3, &pending));
+    EXPECT_TRUE(pending);
+}
+
 }  // namespace sdmmc
diff --git a/zircon/system/dev/block/sdmmc/sdio-controller-device.cpp b/zircon/system/dev/block/sdmmc/sdio-controller-device.cpp
index 0b3c9dd34b5b17a38d5f47131cd550bb35eebecb..e669c69531702957d785c826c61c9d034b937e89 100644
--- a/zircon/system/dev/block/sdmmc/sdio-controller-device.cpp
+++ b/zircon/system/dev/block/sdmmc/sdio-controller-device.cpp
@@ -24,6 +24,8 @@
 
 namespace {
 
+constexpr uint8_t kCccrVendorAddressMin = 0xf0;
+
 constexpr uint32_t kBcmManufacturerId = 0x02d0;
 
 uint32_t SdioReadTupleBody(const uint8_t* tuple_body, size_t start, size_t numbytes) {
@@ -630,6 +632,41 @@ int SdioControllerDevice::SdioIrqThread() {
     return thrd_success;
 }
 
+zx_status_t SdioControllerDevice::SdioIoAbort(uint8_t fn_idx) {
+    if (!SdioFnIdxValid(fn_idx) || fn_idx == 0) {
+        return ZX_ERR_INVALID_ARGS;
+    }
+
+    return SdioDoRwByte(true, 0, SDIO_CIA_CCCR_ASx_ABORT_SEL_CR_ADDR, fn_idx, nullptr);
+}
+
+zx_status_t SdioControllerDevice::SdioIntrPending(uint8_t fn_idx, bool* out_pending) {
+    if (!SdioFnIdxValid(fn_idx) || fn_idx == 0) {
+        return ZX_ERR_INVALID_ARGS;
+    }
+
+    uint8_t intr_byte;
+    zx_status_t st = SdioDoRwByte(false, 0, SDIO_CIA_CCCR_INTx_INTR_PEN_ADDR, 0, &intr_byte);
+    if (st != ZX_OK) {
+        zxlogf(ERROR, "sdio_intr_pending: Failed reading intr pending reg. status: %d\n", st);
+        return st;
+    }
+
+    *out_pending = intr_byte & (1 << fn_idx);
+    return ZX_OK;
+}
+
+zx_status_t SdioControllerDevice::SdioDoVendorControlRwByte(bool write, uint8_t addr,
+                                                            uint8_t write_byte,
+                                                            uint8_t* out_read_byte) {
+    // The vendor area of the CCCR is 0xf0 - 0xff.
+    if (addr < kCccrVendorAddressMin) {
+        return ZX_ERR_OUT_OF_RANGE;
+    }
+
+    return SdioDoRwByte(write, 0, addr, write_byte, out_read_byte);
+}
+
 zx_status_t SdioControllerDevice::SdioReset() {
     zx_status_t st = ZX_OK;
     uint8_t abort_byte;
diff --git a/zircon/system/dev/block/sdmmc/sdio-controller-device.h b/zircon/system/dev/block/sdmmc/sdio-controller-device.h
index 69839e2d57090e61ae0576dc2494543bf487990c..94b42d058865a2f53e3e2c7103301bc5d0ef8126 100644
--- a/zircon/system/dev/block/sdmmc/sdio-controller-device.h
+++ b/zircon/system/dev/block/sdmmc/sdio-controller-device.h
@@ -61,6 +61,10 @@ public:
     virtual zx_status_t SdioDoRwByte(bool write, uint8_t fn_idx, uint32_t addr, uint8_t write_byte,
                                      uint8_t* out_read_byte);
     zx_status_t SdioGetInBandIntr(uint8_t fn_idx, zx::interrupt* out_irq);
+    zx_status_t SdioIoAbort(uint8_t fn_idx);
+    zx_status_t SdioIntrPending(uint8_t fn_idx, bool* out_pending);
+    zx_status_t SdioDoVendorControlRwByte(bool write, uint8_t addr, uint8_t write_byte,
+                                          uint8_t* out_read_byte);
 
     void InBandInterruptCallback();
 
diff --git a/zircon/system/dev/block/sdmmc/sdio-function-device.cpp b/zircon/system/dev/block/sdmmc/sdio-function-device.cpp
index 36c435232bf14b9420f151fb5fd9ad7aaf287833..4a487d39000014bffaca5b298ea50c585f2d4d10 100644
--- a/zircon/system/dev/block/sdmmc/sdio-function-device.cpp
+++ b/zircon/system/dev/block/sdmmc/sdio-function-device.cpp
@@ -98,4 +98,18 @@ zx_status_t SdioFunctionDevice::SdioGetInBandIntr(uint8_t fn_idx, zx::interrupt*
     return sdio_parent_->SdioGetInBandIntr(fn_idx, out_irq);
 }
 
+zx_status_t SdioFunctionDevice::SdioIoAbort(uint8_t fn_idx) {
+    return sdio_parent_->SdioIoAbort(fn_idx);
+}
+
+zx_status_t SdioFunctionDevice::SdioIntrPending(uint8_t fn_idx, bool* out_pending) {
+    return sdio_parent_->SdioIntrPending(fn_idx, out_pending);
+}
+
+zx_status_t SdioFunctionDevice::SdioDoVendorControlRwByte(bool write, uint8_t addr,
+                                                          uint8_t write_byte,
+                                                          uint8_t* out_read_byte) {
+    return sdio_parent_->SdioDoVendorControlRwByte(write, addr, write_byte, out_read_byte);
+}
+
 }  // namespace sdmmc
diff --git a/zircon/system/dev/block/sdmmc/sdio-function-device.h b/zircon/system/dev/block/sdmmc/sdio-function-device.h
index e16776283a56418892d59ffde3945c0b14b48c40..2541e52dde98717a8253ac330b691610a4706c6e 100644
--- a/zircon/system/dev/block/sdmmc/sdio-function-device.h
+++ b/zircon/system/dev/block/sdmmc/sdio-function-device.h
@@ -44,6 +44,10 @@ public:
     zx_status_t SdioDoRwByte(bool write, uint8_t fn_idx, uint32_t addr, uint8_t write_byte,
                              uint8_t* out_read_byte);
     zx_status_t SdioGetInBandIntr(uint8_t fn_idx, zx::interrupt* out_irq);
+    zx_status_t SdioIoAbort(uint8_t fn_idx);
+    zx_status_t SdioIntrPending(uint8_t fn_idx, bool* out_pending);
+    zx_status_t SdioDoVendorControlRwByte(bool write, uint8_t addr, uint8_t write_byte,
+                                          uint8_t* out_read_byte);
 
 private:
     std::atomic<bool> dead_;
diff --git a/zircon/system/dev/lib/mock-sdio/include/lib/mock-sdio/mock-sdio.h b/zircon/system/dev/lib/mock-sdio/include/lib/mock-sdio/mock-sdio.h
index bbb2cca2c90dfdb83bdd185ae1aafc051cdc3815..0ed643b63ca7bca302b868de5f6aef6838c64898 100644
--- a/zircon/system/dev/lib/mock-sdio/include/lib/mock-sdio/mock-sdio.h
+++ b/zircon/system/dev/lib/mock-sdio/include/lib/mock-sdio/mock-sdio.h
@@ -168,6 +168,19 @@ public:
         return ZX_OK;
     }
 
+    zx_status_t SdioIoAbort(uint8_t fn_idx) {
+        return ZX_ERR_NOT_SUPPORTED;
+    }
+
+    zx_status_t SdioIntrPending(uint8_t fn_idx, bool* out_pending) {
+        return ZX_ERR_NOT_SUPPORTED;
+    }
+
+    zx_status_t SdioDoVendorControlRwByte(bool write, uint8_t addr, uint8_t write_byte,
+                                          uint8_t* out_read_byte) {
+        return ZX_ERR_NOT_SUPPORTED;
+    }
+
 private:
     struct SdioRwExpectation {
         uint8_t fn_idx;