[dev][sdhci] switch to BTI

Re-landed version of I8a4bc3a508db17458ddd6324841d1d78306ab320 (git
26c25eb8505e136576ac4a319a77540834b380bd), modified only to build clean.

I believe this was reverted in the bulk revert
335c3a414e169804eb9050d784af6cebd0f5c77f because it did not build
cleanly.  Testing on Acer and Paradise showed no issue.

Change-Id: I10b96fa1a6e3f95aac71c501339abf89174be811
diff --git a/system/dev/block/pci-sdhci/pci-sdhci.c b/system/dev/block/pci-sdhci/pci-sdhci.c
index eb12f3d..be43a3e 100644
--- a/system/dev/block/pci-sdhci/pci-sdhci.c
+++ b/system/dev/block/pci-sdhci/pci-sdhci.c
@@ -25,6 +25,7 @@
     volatile sdhci_regs_t* regs;
     uint64_t regs_size;
     zx_handle_t regs_handle;
+    zx_handle_t bti_handle;
 } pci_sdhci_device_t;
 
 static zx_status_t pci_sdhci_get_interrupt(void* ctx, zx_handle_t* handle_out) {
@@ -63,6 +64,17 @@
     return ZX_OK;
 }
 
+static zx_status_t pci_sdhci_get_bti(void* ctx, uint32_t index, zx_handle_t* out_handle) {
+    pci_sdhci_device_t* dev = ctx;
+    if (dev->bti_handle == ZX_HANDLE_INVALID) {
+        zx_status_t st = pci_get_bti(&dev->pci, index, &dev->bti_handle);
+        if (st != ZX_OK) {
+            return st;
+        }
+    }
+    return zx_handle_duplicate(dev->bti_handle, ZX_RIGHT_SAME_RIGHTS, out_handle);
+}
+
 static uint32_t pci_sdhci_get_base_clock(void* ctx) {
     return 0;
 }
@@ -90,6 +102,7 @@
 static sdhci_protocol_ops_t pci_sdhci_sdhci_proto = {
     .get_interrupt = pci_sdhci_get_interrupt,
     .get_mmio = pci_sdhci_get_mmio,
+    .get_bti = pci_sdhci_get_bti,
     .get_base_clock = pci_sdhci_get_base_clock,
     .get_quirks = pci_sdhci_get_quirks,
     .hw_reset = pci_sdhci_hw_reset,
@@ -105,6 +118,7 @@
     if (dev->regs != NULL) {
         zx_handle_close(dev->regs_handle);
     }
+    zx_handle_close(dev->bti_handle);
     free(dev);
 }
 
diff --git a/system/dev/block/sdhci/sdhci.c b/system/dev/block/sdhci/sdhci.c
index 4facdb2..f5ad649 100644
--- a/system/dev/block/sdhci/sdhci.c
+++ b/system/dev/block/sdhci/sdhci.c
@@ -78,6 +78,8 @@
 
     sdhci_protocol_t sdhci;
 
+    zx_handle_t bti_handle;
+
     // DMA descriptors
     io_buffer_t iobuf;
     sdhci_adma64_desc_t* descs;
@@ -798,6 +800,8 @@
 
 static void sdhci_release(void* ctx) {
     sdhci_device_t* dev = ctx;
+    zx_handle_close(dev->irq_handle);
+    zx_handle_close(dev->bti_handle);
     free(dev);
 }
 
@@ -832,8 +836,9 @@
 
     // allocate and setup DMA descriptor
     if (sdhci_supports_adma2_64bit(dev)) {
-        status = io_buffer_init(&dev->iobuf, DMA_DESC_COUNT * sizeof(sdhci_adma64_desc_t),
-                                IO_BUFFER_RW | IO_BUFFER_CONTIG);
+        status = io_buffer_init_with_bti(&dev->iobuf, dev->bti_handle,
+                                         DMA_DESC_COUNT * sizeof(sdhci_adma64_desc_t),
+                                         IO_BUFFER_RW | IO_BUFFER_CONTIG);
         if (status != ZX_OK) {
             zxlogf(ERROR, "sdhci: error allocating DMA descriptors\n");
             goto fail;
@@ -933,6 +938,12 @@
         goto fail;
     }
 
+    status = dev->sdhci.ops->get_bti(dev->sdhci.ctx, 0, &dev->bti_handle);
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "sdhci: error %d in get_bti\n", status);
+        goto fail;
+    }
+
     status = dev->sdhci.ops->get_interrupt(dev->sdhci.ctx, &dev->irq_handle);
     if (status < 0) {
         zxlogf(ERROR, "sdhci: error %d in get_interrupt\n", status);
@@ -1010,6 +1021,9 @@
         if (dev->irq_handle != ZX_HANDLE_INVALID) {
             zx_handle_close(dev->irq_handle);
         }
+        if (dev->bti_handle != ZX_HANDLE_INVALID) {
+            zx_handle_close(dev->bti_handle);
+        }
         if (dev->iobuf.vmo_handle != ZX_HANDLE_INVALID) {
             zx_handle_close(dev->iobuf.vmo_handle);
         }
diff --git a/system/ulib/ddk/include/ddk/protocol/sdhci.h b/system/ulib/ddk/include/ddk/protocol/sdhci.h
index e508985..72271e2 100644
--- a/system/ulib/ddk/include/ddk/protocol/sdhci.h
+++ b/system/ulib/ddk/include/ddk/protocol/sdhci.h
@@ -14,6 +14,10 @@
     // TODO: should be replaced with a generic busdev mechanism
     zx_status_t (*get_interrupt)(void* ctx, zx_handle_t* handle_out);
     zx_status_t (*get_mmio)(void* ctx, volatile sdhci_regs_t** out);
+    // Gets a handle to the bus transaction initiator for the device. The caller
+    // receives ownership of the handle.
+    zx_status_t (*get_bti)(void* ctx, uint32_t index, zx_handle_t* out_handle);
+
     uint32_t (*get_base_clock)(void* ctx);
 
     // returns device quirks