diff --git a/arch/arm/src/stm32/stm32_sdio.c b/arch/arm/src/stm32/stm32_sdio.c
index 85db660ea415e925f705138f51abe405778b26bd..d5a73ce67649cf3add39a026b378035ea173a4a0 100644
--- a/arch/arm/src/stm32/stm32_sdio.c
+++ b/arch/arm/src/stm32/stm32_sdio.c
@@ -48,7 +48,8 @@
 
 #include "chip.h"
 #include "up_arch.h"
-#include "stm32_internal.h"
+#include "stm32_internal.h"
+#include "stm32_dma.h"
 #include "stm32_sdio.h"
 
 #if CONFIG_STM32_SDIO
@@ -62,6 +63,10 @@
 #if defined(CONFIG_SDIO_DMA) && !defined(CONFIG_STM32_DMA2)
 #  warning "CONFIG_SDIO_DMA support requires CONFIG_STM32_DMA2"
 #  undef CONFIG_SDIO_DMA
+#endif
+
+#ifndef CONFIG_SDIO_DMAPRIO
+#  define CONFIG_SDIO_DMAPRIO DMA_CCR_PRIMED
 #endif
 
 /* Friendly CLKCR bit re-definitions ****************************************/
@@ -87,6 +92,13 @@
 
 #define SDIO_CMDTIMEOUT  100000
 #define SDIO_LONGTIMEOUT 0x7fffffff
+
+/* DMA CCR register settings */
+
+#define SDIO_RXDMA16_CONFIG   (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_16BITS|\
+                               DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC)
+#define SDIO_TXDMA16_CONFIG   (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_16BITS|\
+                               DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
 
 /****************************************************************************
  * Private Types
@@ -96,11 +108,21 @@
 
 struct stm32_dev_s
 {
-  struct sdio_dev_s dev; /* Standard, base MMC/SD interface */
+  struct sdio_dev_s     dev;        /* Standard, base MMC/SD interface */
   
   /* STM32-specific extensions */
-
-  ubyte type;            /* Card type (see MMCSD_CARDTYPE_ definitions) */
+
+  sem_t                 eventsem;   /* Implements event waiting */
+  sdio_event_t          waitevents; /* Set of events to be waited for */
+  volatile sdio_event_t wkupevents; /* Set of events that caused the wakeup */
+  sdio_event_t          cbevents;   /* Set of events to be cause callbacks */
+  sdio_mediachange_t    callback;   /* Registered callback function */
+
+  /* DMA support */
+
+#ifdef CONFIG_SDIO_DMA
+  DMA_HANDLE            dma;        /* Handle for DMA channel */
+#endif
 };
 
 /****************************************************************************
@@ -109,6 +131,8 @@ struct stm32_dev_s
 
 /* Low-level helpers ********************************************************/
 
+static void   stm32_takesem(struct stm32_dev_s *priv);
+#define       stm32_givesem(priv) (sem_post(&priv->waitsem))
 static inline void stm32_setclkcr(uint32 clkcr);
 static inline void stm32_enableint(uint32 bitset);
 static inline void stm32_disableint(uint32 bitset);
@@ -117,9 +141,11 @@ static inline uint32 stm32_getpwrctrl(void);
 static inline void stm32_clkenable(void)
 static inline void stm32_clkdisable(void)
 
-/* DMA Helpers **************************************************************/
-
-static inline void stm32_dmaenable(void);
+/* DMA Helpers **************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static void  stm32_dmacallback(DMA_HANDLE handle, ubyte isr, void *arg);
+#endif
 
 /* Data Transfer Helpers ****************************************************/
 
@@ -155,10 +181,11 @@ static int   stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
 
 /* EVENT handler */
 
-static void  stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset,
+static void  stm32_waitenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset,
                boolean enable);
 static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout);
 static ubyte stm32_events(FAR struct sdio_dev_s *dev);
+static void  stm32_callbackenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset);
 static int   stm32_registercallback(FAR struct sdio_dev_s *dev,
                sdio_mediachange_t callback, void *arg)
 
@@ -166,23 +193,18 @@ static int   stm32_registercallback(FAR struct sdio_dev_s *dev,
 
 #ifdef CONFIG_SDIO_DMA
 static boolean stm32_dmasupported(FAR struct sdio_dev_s *dev);
-#ifdef CONFIG_DATA_CACHE
-static void  stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
-               size_t len, boolean write);
-#endif
 static int   stm32_dmareadsetup(FAR struct sdio_dev_s *dev,
-               FAR ubyte *buffer);
+               FAR ubyte *buffer, size_t buflen);
 static int   stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
-               FAR const ubyte *buffer);
-static int   stm32_dmaenable(FAR struct sdio_dev_s *dev);
+               FAR const ubyte *buffer, size_t buflen);
 static int   stm32_dmastart(FAR struct sdio_dev_s *dev);
-static int   stm32_dmastop(FAR struct sdio_dev_s *dev);
 static int   stm32_dmastatus(FAR struct sdio_dev_s *dev,
                size_t *remaining);
 #endif
 
 /* Initialization/uninitialization/reset ************************************/
-
+
+static void  stm32_callback(void *arg);
 static void  stm32_default(void);
 
 /****************************************************************************
@@ -193,38 +215,35 @@ struct stm32_dev_s g_mmcsd =
 {
   .dev =
   {
-    .reset         = stm32_reset,
-    .status        = stm32_status,
-    .widebus       = stm32_widebus,
-    .clock         = stm32_clock,
-    .attach        = stm32_attach,
-    .sendcmd       = stm32_sendcmd,
-    .sendsetup     = stm32_sendsetup,
-    .senddata      = stm32_senddata,
-    .waitresponse  = stm32_waitresponse,
-    .recvR1        = stm32_recvshortcrc,
-    .recvR2        = stm32_recvlong,
-    .recvR3        = stm32_recvshort,
-    .recvR4        = stm32_recvnotimpl,
-    .recvR5        = stm32_recvnotimpl,
-    .recvR6        = stm32_recvshortcrc,
-    .recvR7        = stm32_recvshort,
-    .recvsetup     = stm32_recvsetup,
-    .recvdata      = stm32_recvdata,
-    .eventenable   = stm32_eventenable,
-    .eventwait     = stm32_eventwait,
-    .events        = stm32_events,
+    .reset            = stm32_reset,
+    .status           = stm32_status,
+    .widebus          = stm32_widebus,
+    .clock            = stm32_clock,
+    .attach           = stm32_attach,
+    .sendcmd          = stm32_sendcmd,
+    .sendsetup        = stm32_sendsetup,
+    .senddata         = stm32_senddata,
+    .waitresponse     = stm32_waitresponse,
+    .recvR1           = stm32_recvshortcrc,
+    .recvR2           = stm32_recvlong,
+    .recvR3           = stm32_recvshort,
+    .recvR4           = stm32_recvnotimpl,
+    .recvR5           = stm32_recvnotimpl,
+    .recvR6           = stm32_recvshortcrc,
+    .recvR7           = stm32_recvshort,
+    .recvsetup        = stm32_recvsetup,
+    .recvdata         = stm32_recvdata,
+    .waitenable       = stm32_waitenable,
+    .eventwait        = stm32_eventwait,
+    .events           = stm32_events,
+    .callbackenable   = stm32_callbackenable,
+    .registercallback = stm32_registercallback,
 #ifdef CONFIG_SDIO_DMA
-    .dmasupported  = stm32_dmasupported,
-#ifdef CONFIG_DATA_CACHE
-    .coherent      = stm32_coherent,
-#endif
-    .dmareadsetup  = stm32_dmareadsetup,
-    .dmawritesetup = stm32_dmawritesetup,
-    .dmaenable     = stm32_dmaenable,
-    .dmastart      = stm32_dmastart,
-    .dmastop       = stm32_dmastop,
-    .dmastatus     = stm32_dmastatus,
+    .dmasupported     = stm32_dmasupported,
+    .dmareadsetup     = stm32_dmareadsetup,
+    .dmawritesetup    = stm32_dmawritesetup,
+    .dmastart         = stm32_dmastart,
+    .dmastatus        = stm32_dmastatus,
 #endif
   },
 };
@@ -236,6 +255,35 @@ struct stm32_dev_s g_mmcsd =
 /****************************************************************************
  * Low-level Helpers
  ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_takesem
+ *
+ * Description:
+ *   Take the wait semaphore (handling false alarm wakeups due to the receipt
+ *   of signals).
+ *
+ * Input Parameters:
+ *   dev - Instance of the SDIO device driver state structure.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32_takesem(struct stm32_dev_s *priv)
+{
+  /* Take the semaphore (perhaps waiting) */
+
+  while (sem_wait(&priv->waitsem) != 0)
+    {
+      /* The only case that an error should occr here is if the wait was
+       * awakened by a signal.
+       */
+
+      ASSERT(errno == EINTR);
+    }
+}
+
 /****************************************************************************
  * Name: stm32_setclkcr
  *
@@ -373,11 +421,32 @@ static inline void stm32_clkdisable(void)
 
 /****************************************************************************
  * DMA Helpers
- ****************************************************************************/
-static inline void stm32_dmaenable(void)
-{
-  putreg32(1, SDIO_DCTRL_DMAEN_BB);
-}
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_dmacallback
+ *
+ * Description:
+ *   Called when SDIO DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static void stm32_dmacallback(DMA_HANDLE handle, ubyte isr, void *arg)
+{
+  FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)arg;
+
+  /* Is a data transfer complete event expected? */
+
+  if ((priv->waitevents & SDIOWAIT_TRANSFERDONE) != 0)
+    {
+      /* Yes, wake up the waiting thread */
+
+      priv->wkupevent = SDIOWAIT_TRANSFERDONE;
+      sdio_semgive(priv);
+    }
+}
+#endif
 
 /****************************************************************************
  * Data Transfer Helpers
@@ -1008,14 +1077,22 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
 }
 
 /****************************************************************************
- * Name: stm32_eventenable
+ * Name: stm32_waitenable
  *
  * Description:
- *   Enable/disable notification of a set of MMC/SD events
- *
+ *   Enable/disable of a set of MMC/SD wait events.  This is part of the
+ *   the SDIO_WAITEVENT sequence.  The set of to-be-waited-for events is
+ *   configured before calling stm32_waitevent.  This is done in this way
+ *   to help the driver to eliminate race conditions between the command
+ *   setup and the subsequent events.
+ *
+ *   The enabled events persist until either (1) SDIO_WAITENABLE is called
+ *   again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
+ *   returns.
+ *
  * Input Parameters:
  *   dev      - An instance of the MMC/SD device interface
- *   eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
+ *   eventset - A bitset of events to enable or disable (see SDIOWAIT_*
  *              definitions). 0=disable; 1=enable.
  *
  * Returned Value:
@@ -1023,15 +1100,26 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
  *
  ****************************************************************************/
 
-static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
-{
+static void stm32_waitenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
+{
+  struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+
+  /* This odd sequence avoids race conditions */
+
+  DEBUGASSERT(priv != NULL);
+  priv->waitevents = 0;
+  priv->wkupevents = 0;
+  priv->waitevents = eventset;
 }
 
 /****************************************************************************
  * Name: stm32_eventwait
  *
  * Description:
- *   Wait for one of the enabled events to occur (or a timeout)
+ *   Wait for one of the enabled events to occur (or a timeout).  Note that
+ *   all events enabled by SDIO_WAITEVENTS are disabled when stm32_eventwait
+ *   returns.  SDIO_WAITEVENTS must be called again before stm32_eventwait
+ *   can be used again.
  *
  * Input Parameters:
  *   dev     - An instance of the MMC/SD device interface
@@ -1045,8 +1133,42 @@ static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
  ****************************************************************************/
 
 static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout)
-{
-  return 0;
+{
+  ubyte wkupevents = 0;
+
+  DEBUGASSERT(priv->waitevents != 0);
+
+  /* Loop until the event (or the timeout occurs). Race conditions are avoided
+   * by calling stm32_waitenable prior to triggering the logic that will cause
+   * the wait to terminate.  Under certain race conditions, the waited-for
+   * may have already occurred before this function was called!
+   */
+#warning "Timeout logic not implemented"
+  for (;;)
+    {
+      /* Wait for an event in event set to occur.  If this the event has already
+       * occurred, then the semaphore will already have been incremented and
+       * there will be no wait.
+       */
+
+      stm32_takesem(priv);
+
+      /* Check if the event has occurred. */
+
+      wkupevents = (ubyte)(priv->wkupevents & priv->waitevents)
+      if (wkupevents != 0)
+        {
+          /* Yes... break out of the loop with wkupevents non-zero */
+
+          break;
+        }
+    }
+
+  /* Clear all enabled wait events before returning */
+
+  priv->waitevents = 0;
+  priv->wkupevents = 0;
+  return wkupevents;
 }
 
 /****************************************************************************
@@ -1070,6 +1192,36 @@ static ubyte stm32_events(FAR struct sdio_dev_s *dev)
   return 0;
 }
 
+/****************************************************************************
+ * Name: stm32_callbackenable
+ *
+ * Description:
+ *   Enable/disable of a set of MMC/SD callback events.  This is part of the
+ *   the SDIO callback sequence.  The set of events is configured to enabled
+ *   callbacks to the function provided in stm32_registercallback.
+ *
+ *   Events are automatically disabled once the callback is performed and no
+ *   further callback events will occur until they are again enabled by
+ *   calling this methos.
+ *
+ * Input Parameters:
+ *   dev      - An instance of the MMC/SD device interface
+ *   eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
+ *              definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32_callbackenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
+{
+  struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+  DEBUGASSERT(priv != NULL);
+  priv->cbevents = eventset;
+  stm32_callback(priv);
+}
+
 /****************************************************************************
  * Name: stm32_registercallback
  *
@@ -1079,6 +1231,9 @@ static ubyte stm32_events(FAR struct sdio_dev_s *dev)
  *   interrupt level events should be handled by calling back on the work
  *   thread.
  *
+ *   When this method is called, all callbacks should be disabled until they
+ *   are enabled via a call to SDIO_CALLBACKENABLE
+ *
  * Input Parameters:
  *   dev -      Device-specific state data
  *   callback - The funtion to call on the media change
@@ -1092,7 +1247,15 @@ static ubyte stm32_events(FAR struct sdio_dev_s *dev)
 static int stm32_registercallback(FAR struct sdio_dev_s *dev,
                                   sdio_mediachange_t callback, void *arg)
 {
-  return -ENOSYS;
+  struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
+
+  /* Disable callbacks and register this callback and is argument */
+
+  DEBUGASSERT(priv != NULL);
+  priv->cbevents = 0;
+  priv->cbarg    = arg;
+  priv->callback = callback;
+  return OK;
 }
 
 /****************************************************************************
@@ -1116,44 +1279,19 @@ static boolean stm32_dmasupported(FAR struct sdio_dev_s *dev)
 }
 #endif
 
-/****************************************************************************
- * Name: stm32_coherent
- *
- * Description:
- *   If the processor supports a data cache, then this method will make sure
- *   that the contents of the DMA memory and the data cache are coherent in
- *   preparation for the DMA transfer.  For write transfers, this may mean
- *   flushing the data cache, for read transfers this may mean invalidating
- *   the data cache.
- *
- * Input Parameters:
- *   dev   - An instance of the MMC/SD device interface
- *   addr  - The beginning address of the DMA
- *   len   - The length of the DMA
- *   write - TRUE: A write DMA will be performed; FALSE: a read DMA will be
- *           performed.
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_DATA_CACHE)
-static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
-                           size_t len, boolean write)
-{
-}
-#endif
-
 /****************************************************************************
  * Name: stm32_dmareadsetup
  *
  * Description:
- *   Setup to perform a read DMA
+ *   Setup to perform a read DMA.  If the processor supports a data cache,
+ *   then this method will also make sure that the contents of the DMA memory
+ *   and the data cache are coherent.  For read transfers this may mean
+ *   invalidating the data cache.
  *
  * Input Parameters:
  *   dev    - An instance of the MMC/SD device interface
  *   buffer - The memory to DMA from
+ *   buflen - The size of the DMA transfer in bytes
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
@@ -1161,9 +1299,12 @@ static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
  ****************************************************************************/
 
 #ifdef CONFIG_SDIO_DMA
-static int  tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
+static int  tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer, size_t buflen)
 {
-  return -ENOSYS;
+  /* Configure the RX DMA */
+
+  stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32)buffer,
+                 (buflen + 3) >> 2, SDIO_RXDMA16_CONFIG);
 }
 #endif
 
@@ -1171,11 +1312,15 @@ static int  tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
  * Name: stm32_dmawritesetup
  *
  * Description:
- *   Setup to perform a write DMA
+ *   Setup to perform a write DMA.  If the processor supports a data cache,
+ *   then this method will also make sure that the contents of the DMA memory
+ *   and the data cache are coherent.  For write transfers, this may mean
+ *   flushing the data cache.
  *
  * Input Parameters:
  *   dev    - An instance of the MMC/SD device interface
  *   buffer - The memory to DMA into
+ *   buflen - The size of the DMA transfer in bytes
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
@@ -1184,9 +1329,12 @@ static int  tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
 
 #ifdef CONFIG_SDIO_DMA
 static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
-                               FAR const ubyte *buffer)
+                               FAR const ubyte *buffer, size_t buflen)
 {
-  return -ENOSYS;
+  /* Configure the RX DMA */
+
+  stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32)buffer,
+                 (buflen + 3) >> 2, SDIO_TXDMA16_CONFIG);
 }
 #endif
 
@@ -1206,29 +1354,8 @@ static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
 
 #ifdef CONFIG_SDIO_DMA
 static int stm32_dmastart(FAR struct sdio_dev_s *dev)
-{
-  return -ENOSYS;
-}
-#endif
-
-/****************************************************************************
- * Name: stm32_dmastop
- *
- * Description:
- *   Stop the DMA
- *
- * Input Parameters:
- *   dev - An instance of the MMC/SD device interface
- *
- * Returned Value:
- *   OK on success; a negated errno on failure
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SDIO_DMA
-static int stm32_dmastop(FAR struct sdio_dev_s *dev)
-{
-  return -ENOSYS;
+{
+   stm32_dmastart(priv->dma, sdio_dmacallback, priv, FALSE);
 }
 #endif
 
@@ -1236,7 +1363,7 @@ static int stm32_dmastop(FAR struct sdio_dev_s *dev)
  * Name: stm32_dmastatus
  *
  * Description:
- *   Returnt the number of bytes remaining in the DMA transfer
+ *   Return the number of bytes remaining in the DMA transfer
  *
  * Input Parameters:
  *   dev       - An instance of the MMC/SD device interface
@@ -1268,6 +1395,63 @@ static int stm32_dmastatus(FAR struct sdio_dev_s *dev, size_t *remaining)
 /****************************************************************************
  * Initialization/uninitialization/reset
  ****************************************************************************/
+/****************************************************************************
+ * Name: stm32_callback
+ *
+ * Description:
+ *   Perform callback.
+ *
+ * Assumptions:
+ *   This function does not execute in the context of an interrupt handler.
+ *   It may be invoked on any user thread or scheduled on the work thread
+ *   from an interrupt handler.
+ *
+ ****************************************************************************/
+
+static void stm32_callback(void *arg)
+{
+  struct stm32_dev_s *priv = (struct stm32_dev_s*)arg;
+
+  /* Is a callback registered? */
+
+  DEBUGASSERT(priv != NULL);
+  if (priv->callback)
+    {
+      /* Yes.. Check for enabled callback events */
+
+      if ((stm32_status(&priv->dev) & SDIO_STATUS_PRESENT) != 0)
+        {
+          /* Media is present.  Is the media inserted event enabled? */
+
+          if ((priv->cbevents & SDIOMEDIA_INSERTED) == 0)
+           {
+             /* No... return without performing the callback */
+
+              return;
+            }
+        }
+      else
+        {
+          /* Media is not present.  Is the media eject event enabled? */
+
+          if ((priv->cbevents & SDIOMEDIA_EJECTED) == 0)
+            {
+              /* No... return without performing the callback */
+
+              return;
+            }
+        }
+
+      /* Perform the callback, disabling further callbacks.  Of course, the
+       * the callback can (and probably should) re-enable callbacks.
+       */
+
+      priv->cbevents = 0;
+      priv->callback(priv->cbarg);
+      
+    }
+}
+
 /****************************************************************************
  * Name: stm32_default
  *
@@ -1294,24 +1478,35 @@ static void stm32_default(void)
  ****************************************************************************/
 
 /****************************************************************************
- * Name: mmcsd_slotinitialize
+ * Name: sdio_initialize
  *
  * Description:
- *   Initialize one slot for operation using the MMC/SD interface
+ *   Initialize SDIO for operation.
  *
- * Input Parameters:
- *   minor - The MMC/SD minor device number.  The MMC/SD device will be
- *     registered as /dev/mmcsdN where N is the minor number
- *   slotno - The slot number to use.  This is only meaningful for architectures
- *     that support multiple MMC/SD slots.  This value must be in the range
- *     {0, ..., CONFIG_MMCSD_NSLOTS}.
- *   dev - And instance of an MMC/SD interface.  The MMC/SD hardware should
- *     be initialized and ready to use.
+ * Input Parameters:
+ *   slotno - Not used.
+ *
+ * Returned Values:
+ *   A reference to an SDIO interface structure.  NULL is returned on failures.
  *
  ****************************************************************************/
 
-int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
-{
+FAR sdio_dev_s *mmcsd_slotinitialize(int slotno)
+{
+  /* There is only one, slot */
+
+  struct stm32_dev_s *priv = &g_sdiodev;
+
+  /* Initialize the SDIO slot structure */
+
+  sem_init(&priv->eventsem, 0, 0);
+
+  /* Allocate a DMA channel */
+
+#ifdef CONFIG_SDIO_DMA
+  priv->dma = stm32_dmachannel(DMACHAN_SDIO);
+#endif
+
   /* Configure GPIOs for 4-bit, wide-bus operation (the chip is capable of
    * 8-bit wide bus operation but D4-D7 are not configured).
    */
@@ -1332,8 +1527,8 @@ int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
   stm32_setclkcr(STM32_CLCKCR_INIT);
   stm32_setpwrctrl(SDIO_POWER_PWRCTRL_ON);
   stm32_clkenable(ENABLE);
-
-  return -ENOSYS;
+
+  return &g_sdiodev.dev;
 }
 
 #endif /* CONFIG_STM32_SDIO */
diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c
index cab079556c64994c30bb0d8c8dd7d3867bf33433..76663c8c5b6cf3cbff567ac5ff932605246bb1a9 100644
--- a/drivers/mmcsd/mmcsd_sdio.c
+++ b/drivers/mmcsd/mmcsd_sdio.c
@@ -372,7 +372,7 @@ static int mmcsd_getSCR(struct mmcsd_state_s *priv, uint32 scr[2])
 
   /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 to start data receipt */
 
-  (void)SDIO_EVENTENABLE(priv->dev, SDIOEVENT_READDATADONE);
+  (void)SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE);
   mmcsd_sendcmdpoll(priv, SD_ACMD51, 0);
   ret = mmcsd_recvR1(priv, SD_ACMD51);
   if (ret != OK)
@@ -1063,6 +1063,10 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
           {
             fdbg("ERROR: mmcsd_removed failed: %d\n", ret);
           }
+ 
+        /* Enable logic to detect if a card is re-inserted */
+
+        SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
       }
       break;
 
@@ -1117,6 +1121,10 @@ static void mmcsd_mediachange(FAR void *arg)
        */
 
       (void)mmcsd_removed(priv);
+
+      /* Enable logic to detect if a card is re-inserted */
+
+      SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
     }
   mmcsd_givesem(priv);
 }
@@ -1743,7 +1751,7 @@ static int mmcsd_probe(struct mmcsd_state_s *priv)
       if (ret != OK)
         {
           fdbg("ERROR: Failed to initialize card: %d\n");
-          SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
+          SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
         }
       else
         {
@@ -1780,7 +1788,7 @@ static int mmcsd_probe(struct mmcsd_state_s *priv)
 
                 /* Set up to receive asynchronous, media removal events */
 
-                SDIO_EVENTENABLE(priv->dev, SDIOEVENT_EJECTED);
+                SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_EJECTED);
               }
         }
 
@@ -1793,7 +1801,7 @@ static int mmcsd_probe(struct mmcsd_state_s *priv)
       /* There is no card in the slot */
 
       fvdbg("No card\n");
-      SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
+      SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
       ret = -ENODEV;
     }
 
@@ -1835,10 +1843,6 @@ static int mmcsd_removed(struct mmcsd_state_s *priv)
   /* Disable clocking to the card */
 
   (void)SDIO_CLOCK(priv->dev, CLOCK_SDIO_DISABLED);
-
-  /* Enable logic to detect if a card is re-inserted */
-
-  SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
   return OK;
 }
 
@@ -1874,7 +1878,7 @@ static int mmcsd_hwinitialize(struct mmcsd_state_s *priv)
   fvdbg("Successfully attached MMC/SD interrupts\n");
 
   /* Register a callback so that we get informed if media is inserted or
-   * removed from the slot.
+   * removed from the slot (Initially all callbacks are disabled).
    */
 
   SDIO_REGISTERCALLBACK(priv->dev, mmcsd_mediachange, (FAR void *)priv);
@@ -1917,7 +1921,7 @@ static int mmcsd_hwinitialize(struct mmcsd_state_s *priv)
     {
       /* No... Setup to receive the media inserted event */
 
-      SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
+      SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
 
       /* ENODEV is returned to indicate that no card is inserted in the slot. */
 
diff --git a/include/nuttx/sdio.h b/include/nuttx/sdio.h
index 576526a0ec0e2d172cc41130bc4ee09a00b72d6f..cf347058578a35a8000b8719580d71de6dc57ace 100755
--- a/include/nuttx/sdio.h
+++ b/include/nuttx/sdio.h
@@ -47,18 +47,21 @@
  * Pre-Processor Definitions
  ****************************************************************************/
 
-/* MMC/SD events needed by the driver */
+/* MMC/SD events needed by the driver
+ *
+ * Wait events are used for event-waiting by SDIO_WAITENABLE and SDIO_EVENTWAIT
+ */
+
+#define SDIOWAIT_CMDDONE       (1 << 0) /* Bit 0: Command+response complete */
+#define SDIOWAIT_CMDBUSYDONE   (1 << 1) /* Bit 1: Command with transition to not busy */
+#define SDIOWAIT_TRANSFERDONE  (1 << 2) /* Bit 2: Data transfer/DMA done */
+
+#define SDIOWAIT_ALLEVENTS     0x03
 
-#define SDIOEVENT_EJECTED       (1 << 0) /* Bit 0: CD/DAT3 transition low, media removed */
-#define SDIOEVENT_INSERTED      (1 << 1) /* Bit 1: CD/DAT3 transition high, media inserted */
-#define SDIOEVENT_CMDDONE       (1 << 2) /* Bit 2: Command+response complete */
-#define SDIOEVENT_READCMDDONE   (1 << 3) /* Bit 3: Read command done */
-#define SDIOEVENT_WRITECMDDONE  (1 << 4) /* Bit 4: Write command done */
-#define SDIOEVENT_READDATADONE  (1 << 5) /* Bit 5: Read data done */
-#define SDIOEVENT_WRITEDATADONE (1 << 6) /* Bit 6: Write data done */
-#define SDIOEVENT_CMDBUSYDONE   (1 << 7) /* Bit 7: Command with transition to not busy */
+/* Media events are used for enable/disable registered event callbacks */
 
-#define SDIOEVENT_ALLEVENTS     0xff
+#define SDIOMEDIA_EJECTED       (1 << 0) /* Bit 0: Mmedia removed */
+#define SDIOMEDIA_INSERTED      (1 << 1) /* Bit 1: Media inserted */
 
 /* Commands are bit-encoded to provide as much information to the SDIO driver as
  * possible in 32-bits.  The encoding is as follows:
@@ -517,14 +520,22 @@
 #define SDIO_RECVDATA(dev,buffer) ((dev)->recvdata(dev,buffer))
 
 /****************************************************************************
- * Name: SDIO_EVENTENABLE
+ * Name: SDIO_WAITENABLE
  *
  * Description:
- *   Enable/disable notification of a set of MMC/SD events
+ *   Enable/disable of a set of MMC/SD wait events.  This is part of the
+ *   the SDIO_WAITEVENT sequence.  The set of to-be-waited-for events is
+ *   configured before calling SDIO_EVENTWAIT.  This is done in this way
+ *   to help the driver to eliminate race conditions between the command
+ *   setup and the subsequent events.
+ *
+ *   The enabled events persist until either (1) SDIO_WAITENABLE is called
+ *   again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
+ *   returns.
  *
  * Input Parameters:
  *   dev      - An instance of the MMC/SD device interface
- *   eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
+ *   eventset - A bitset of events to enable or disable (see SDIOWAIT_*
  *              definitions). 0=disable; 1=enable.
  *
  * Returned Value:
@@ -532,13 +543,16 @@
  *
  ****************************************************************************/
 
-#define SDIO_EVENTENABLE(dev,eventset)  ((dev)->eventenable(dev,eventset))
+#define SDIO_WAITENABLE(dev,eventset)  ((dev)->waitenable(dev,eventset))
 
 /****************************************************************************
  * Name: SDIO_EVENTWAIT
  *
  * Description:
- *   Wait for one of the enabled events to occur (or a timeout)
+ *   Wait for one of the enabled events to occur (or a timeout).  Note that
+ *   all events enabled by SDIO_WAITEVENTS are disabled when SDIO_EVENTWAIT
+ *   returns.  SDIO_WAITEVENTS must be called again before SDIO_EVENTWAIT
+ *   can be used again.
  *
  * Input Parameters:
  *   dev     - An instance of the MMC/SD device interface
@@ -571,6 +585,30 @@
 
 #define SDIO_EVENTS(dev)  ((dev)->events(dev))
 
+/****************************************************************************
+ * Name: SDIO_CALLBACKENABLE
+ *
+ * Description:
+ *   Enable/disable of a set of MMC/SD callback events.  This is part of the
+ *   the SDIO callback sequence.  The set of events is configured to enabled
+ *   callbacks to the function provided in SDIO_REGISTERCALLBACK.
+ *
+ *   Events are automatically disabled once the callback is performed and no
+ *   further callback events will occur until they are again enabled by
+ *   calling this methos.
+ *
+ * Input Parameters:
+ *   dev      - An instance of the MMC/SD device interface
+ *   eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
+ *              definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#define SDIO_CALLBACKENABLE(dev,eventset)  ((dev)->waitenable(dev,eventset))
+
 /****************************************************************************
  * Name: SDIO_REGISTERCALLBACK
  *
@@ -580,6 +618,9 @@
  *   interrupt level events should be handled by calling back on the work
  *   thread.
  *
+ *   When this method is called, all callbacks should be disabled until they
+ *   are enabled via a call to SDIO_CALLBACKENABLE
+ *
  * Input Parameters:
  *   dev -      Device-specific state data
  *   callback - The funtion to call on the media change
@@ -612,43 +653,19 @@
 #  define SDIO_DMASUPPORTED(dev) (FALSE)
 #endif
 
-/****************************************************************************
- * Name: SDIO_COHERENT
- *
- * Description:
- *   If the processor supports a data cache, then this method will make sure
- *   that the contents of the DMA memory and the data cache are coherent in
- *   preparation for the DMA transfer.  For write transfers, this may mean
- *   flushing the data cache, for read transfers this may mean invalidating
- *   the data cache.
- *
- * Input Parameters:
- *   dev   - An instance of the MMC/SD device interface
- *   addr  - The beginning address of the DMA
- *   len   - The length of the DMA
- *   write - TRUE: A write DMA will be performed; FALSE: a read DMA will be
- *           performed.
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_DATA_CACHE)
-#  define SDIO_COHERENT(dev,addr,len,write) ((dev)->coherent(dev,addr,len,write))
-#else
-#  define SDIO_COHERENT(dev,addr,len,write)
-#endif
-
 /****************************************************************************
  * Name: SDIO_DMAREADSETUP
  *
  * Description:
- *   Setup to perform a read DMA
+ *   Setup to perform a read DMA.  If the processor supports a data cache,
+ *   then this method will also make sure that the contents of the DMA memory
+ *   and the data cache are coherent.  For read transfers this may mean
+ *   invalidating the data cache.
  *
  * Input Parameters:
  *   dev    - An instance of the MMC/SD device interface
  *   buffer - The memory to DMA from
+ *   buflen - The size of the DMA transfer in bytes
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
@@ -656,20 +673,24 @@
  ****************************************************************************/
 
 #ifdef CONFIG_SDIO_DMA
-#  define SDIO_DMAREADSETUP(dev,buffer) ((dev)->dmareadsetup(dev,buffer))
+#  define SDIO_DMAREADSETUP(dev,buffer,len) ((dev)->dmareadsetup(dev,buffer,len))
 #else
-#  define SDIO_DMAREADSETUP(dev,buffer) (-ENOSYS)
+#  define SDIO_DMAREADSETUP(dev,buffer,len) (-ENOSYS)
 #endif
 
 /****************************************************************************
  * Name: SDIO_DMAWRITESETUP
  *
  * Description:
- *   Setup to perform a write DMA
+ *   Setup to perform a write DMA.  If the processor supports a data cache,
+ *   then this method will also make sure that the contents of the DMA memory
+ *   and the data cache are coherent.  For write transfers, this may mean
+ *   flushing the data cache.
  *
  * Input Parameters:
  *   dev    - An instance of the MMC/SD device interface
  *   buffer - The memory to DMA into
+ *   buflen - The size of the DMA transfer in bytes
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
@@ -677,9 +698,9 @@
  ****************************************************************************/
 
 #ifdef CONFIG_SDIO_DMA
-#  define SDIO_DMAWRITESETUP(dev,buffer) ((dev)->dmawritesetup(dev,buffer))
+#  define SDIO_DMAWRITESETUP(dev,buffer,len) ((dev)->dmawritesetup(dev,buffer,len))
 #else
-#  define SDIO_DMAWRITESETUP(dev,buffer) (-ENOSYS)
+#  define SDIO_DMAWRITESETUP(dev,buffer,len) (-ENOSYS)
 #endif
 
 /****************************************************************************
@@ -702,31 +723,11 @@
 #  define SDIO_DMASTART(dev) (-ENOSYS)
 #endif
 
-/****************************************************************************
- * Name: SDIO_DMASTOP
- *
- * Description:
- *   Stop the DMA
- *
- * Input Parameters:
- *   dev - An instance of the MMC/SD device interface
- *
- * Returned Value:
- *   OK on success; a negated errno on failure
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SDIO_DMA
-#  define SDIO_DMASTOP(dev) ((dev)->dmastop(dev))
-#else
-#  define SDIO_DMASTOP(dev) (-ENOSYS)
-#endif
-
 /****************************************************************************
  * Name: SDIO_DMASTATUS
  *
  * Description:
- *   Returnt the number of bytes remaining in the DMA transfer
+ *   Return the number of bytes remaining in the DMA transfer
  *
  * Input Parameters:
  *   dev       - An instance of the MMC/SD device interface
@@ -810,7 +811,7 @@ struct sdio_dev_s
 
   /* EVENT handler */
 
-  void  (*eventenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
+  void  (*waitenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
   ubyte (*eventwait)(FAR struct sdio_dev_s *dev, uint32 timeout);
   ubyte (*events)(FAR struct sdio_dev_s *dev);
   int   (*registercallback)(FAR struct sdio_dev_s *dev, sdio_mediachange_t callback, void *arg);
@@ -819,13 +820,11 @@ struct sdio_dev_s
 
 #ifdef CONFIG_SDIO_DMA
   boolean (*dmasupported)(FAR struct sdio_dev_s *dev);
-#ifdef CONFIG_DATA_CACHE
-  void  (*coherent)(FAR struct sdio_dev_s *dev, FAR void *addr, size_t len, boolean write);
-#endif
-  int   (*dmareadsetup)(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
-  int   (*dmawritesetup)(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer);
-  int   (*dmaenable)(FAR struct sdio_dev_s *dev);
-  int   (*dmastop)(FAR struct sdio_dev_s *dev);
+  int   (*dmareadsetup)(FAR struct sdio_dev_s *dev, FAR ubyte *buffer,
+          size_t buflen);
+  int   (*dmawritesetup)(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer,
+          size_t buflen);
+  int   (*dmastart)(FAR struct sdio_dev_s *dev);
   int   (*dmastatus)(FAR struct sdio_dev_s *dev, size_t *remaining);
 #endif
 };