diff -Naur freeipmi/libfreeipmi/include/freeipmi/api/ipmi-api.h freeipmi.mods/libfreeipmi/include/freeipmi/api/ipmi-api.h
--- freeipmi/libfreeipmi/include/freeipmi/api/ipmi-api.h	2010-02-05 17:53:04.000000000 -0700
+++ freeipmi.mods/libfreeipmi/include/freeipmi/api/ipmi-api.h	2010-02-23 09:10:51.000000000 -0700
@@ -217,6 +217,17 @@
 
 void ipmi_ctx_destroy (ipmi_ctx_t ctx);
 
+/* Blocking function to wait for events from BMC.*/
+/* Application should call ipmi_cmd_get_message_flags to
+   determine the event source */
+/* returns 0 on success, -1 on error */
+int ipmi_ctx_wait_event(ipmi_ctx_t ctx);
+
+/* Releases the thread blocked on ipmi_ctx_wait_event */
+/* Useful when closing the application gracefully */
+/* returns 0 on success, -1 on error */
+int ipmi_ctx_clear_wait_event(ipmi_ctx_t ctx);
+
 #ifdef __cplusplus
 }
 #endif
diff -Naur freeipmi/libfreeipmi/src/api/ipmi-api.c freeipmi.mods/libfreeipmi/src/api/ipmi-api.c
--- freeipmi/libfreeipmi/src/api/ipmi-api.c	2010-02-05 17:53:05.000000000 -0700
+++ freeipmi.mods/libfreeipmi/src/api/ipmi-api.c	2010-02-23 09:10:51.000000000 -0700
@@ -2033,3 +2033,45 @@
   secure_memset (ctx, '\0', sizeof (ipmi_ctx_t));
   free (ctx);
 }
+
+int 
+ipmi_ctx_wait_event(ipmi_ctx_t ctx)
+{
+  if (!ctx || ctx->magic != IPMI_CTX_MAGIC)
+    {
+      ERR_TRACE (ipmi_ctx_errormsg (ctx), ipmi_ctx_errnum (ctx));
+      return -1;
+    }
+
+  /* Only the KCS interface supports this feature */
+  if (ctx->type == IPMI_DEVICE_KCS)
+    {
+      return(ipmi_kcs_cmd_wait_event(ctx));
+    }
+  else
+    {
+      API_SET_ERRNUM(ctx, IPMI_ERR_DEVICE_NOT_SUPPORTED);
+      return -1;
+    }
+}
+
+int 
+ipmi_ctx_clear_wait_event(ipmi_ctx_t ctx)
+{
+  if (!ctx || ctx->magic != IPMI_CTX_MAGIC)
+    {
+      ERR_TRACE (ipmi_ctx_errormsg (ctx), ipmi_ctx_errnum (ctx));
+      return -1;
+    }
+
+  /* Only the KCS interface supports this feature */
+  if (ctx->type == IPMI_DEVICE_KCS)
+    {
+      return(ipmi_kcs_cmd_clear_wait_event(ctx));
+    }
+  else
+    {
+      API_SET_ERRNUM(ctx, IPMI_ERR_DEVICE_NOT_SUPPORTED);
+      return -1;
+    }
+}
diff -Naur freeipmi/libfreeipmi/src/api/ipmi-kcs-driver-api.c freeipmi.mods/libfreeipmi/src/api/ipmi-kcs-driver-api.c
--- freeipmi/libfreeipmi/src/api/ipmi-kcs-driver-api.c	2010-02-05 17:53:05.000000000 -0700
+++ freeipmi.mods/libfreeipmi/src/api/ipmi-kcs-driver-api.c	2010-02-23 09:10:51.000000000 -0700
@@ -843,3 +843,39 @@
   fiid_obj_destroy (obj_cmd_rs);
   return (rv);
 }
+
+int
+ipmi_kcs_cmd_wait_event (ipmi_ctx_t ctx)
+{
+  if (!ctx || ctx->magic != IPMI_CTX_MAGIC)
+    {
+      ERR_TRACE (ipmi_ctx_errormsg (ctx), ipmi_ctx_errnum (ctx));
+      return (-1);
+    }
+
+  if (ctx->type != IPMI_DEVICE_KCS)
+    {
+      API_SET_ERRNUM (ctx, IPMI_ERR_INTERNAL_ERROR);
+      return (-1);
+    }
+
+  return (ipmi_kcs_wait(ctx->io.inband.kcs_ctx));
+}
+
+int
+ipmi_kcs_cmd_clear_wait_event (ipmi_ctx_t ctx)
+{
+  if (!ctx || ctx->magic != IPMI_CTX_MAGIC)
+    {
+      ERR_TRACE (ipmi_ctx_errormsg (ctx), ipmi_ctx_errnum (ctx));
+      return (-1);
+    }
+
+  if (ctx->type != IPMI_DEVICE_KCS)
+    {
+      API_SET_ERRNUM (ctx, IPMI_ERR_INTERNAL_ERROR);
+      return (-1);
+    }
+
+  return (ipmi_kcs_clear_wait(ctx->io.inband.kcs_ctx));
+}
diff -Naur freeipmi/libfreeipmi/src/api/ipmi-kcs-driver-api.h freeipmi.mods/libfreeipmi/src/api/ipmi-kcs-driver-api.h
--- freeipmi/libfreeipmi/src/api/ipmi-kcs-driver-api.h	2010-02-05 17:53:05.000000000 -0700
+++ freeipmi.mods/libfreeipmi/src/api/ipmi-kcs-driver-api.h	2010-02-23 09:10:51.000000000 -0700
@@ -48,5 +48,8 @@
 			       void *buf_rs,
 			       unsigned int buf_rs_len);
 
+int ipmi_kcs_cmd_wait_event (ipmi_ctx_t ctx);
+int ipmi_kcs_cmd_clear_wait_event (ipmi_ctx_t ctx);
+
 #endif /* ipmi-kcs-driver-api.h */
 
diff -Naur freeipmi/libfreeipmi/src/driver/ipmi-kcs-driver.c freeipmi.mods/libfreeipmi/src/driver/ipmi-kcs-driver.c
--- freeipmi/libfreeipmi/src/driver/ipmi-kcs-driver.c	2010-02-05 17:53:06.000000000 -0700
+++ freeipmi.mods/libfreeipmi/src/driver/ipmi-kcs-driver.c	2010-02-23 09:15:04.000000000 -0700
@@ -137,6 +137,8 @@
 
 #define IPMI_KCS_FLAGS_MASK IPMI_KCS_FLAGS_NONBLOCKING
 
+#define IPMI_KCS_PROJ_ID IPMI_KCS_CTX_MAGIC
+
 #if defined(__FreeBSD__)
 # include <machine/cpufunc.h>
 # include <machine/sysarch.h>
@@ -196,6 +198,7 @@
 #endif /* __FreeBSD__ */
   int io_init;
   int semid;
+  int event_sem;
 };
 
 static void
@@ -275,6 +278,14 @@
       ERRNO_TRACE (errno);
       goto cleanup;
     }
+
+  /* Create semaphore to signal events to application.  Set
+     initial value of the number of events to 0 */
+  if (ctx->event_sem = ipmi_mutex_init_values(IPMI_KCS_PROJ_ID, 0) < 0)
+      {
+       ERRNO_TRACE (errno);
+       goto cleanup;      
+      }
   ctx->errnum = IPMI_KCS_ERR_SUCCESS;
   return (ctx);
 
@@ -517,15 +528,44 @@
   return (0);
 }
 
+static void
+_ipmi_kcs_check_sms_atn(ipmi_kcs_ctx_t ctx, int8_t reg_status)
+{
+  static uint8_t prev_sms_atn = 0;
+  uint8_t curr_sms_atn = reg_status &= IPMI_KCS_STATUS_REG_SMS_ATN;
+
+  /* Check if sms_atn bit changed */
+  if (curr_sms_atn != prev_sms_atn)
+    {
+      /* SMS-ATN just changed.  Check if it's now set */
+      if (curr_sms_atn)
+        {
+          /* sms_atn bit was just set.  Unlock any threads
+             waiting for events */
+          ipmi_mutex_unlock(ctx->event_sem);
+        }
+    }
+
+  /* Save off the sms_atn value */
+  prev_sms_atn = curr_sms_atn;
+}
+
 static int8_t
 _ipmi_kcs_get_status (ipmi_kcs_ctx_t ctx)
 {
+  int8_t reg_status;
   assert (ctx);
   assert (ctx->magic == IPMI_KCS_CTX_MAGIC);
 
-  return (_INB (IPMI_KCS_REG_STATUS (ctx->driver_address, ctx->register_spacing)));
+  reg_status = _INB (IPMI_KCS_REG_STATUS (ctx->driver_address, ctx->register_spacing));
+
+  /* Check if the sms_atn bit is set */
+  _ipmi_kcs_check_sms_atn(ctx, reg_status);
+
+  return(reg_status);
 }
 
+
 /*
  * Wait for IBF (In-Bound Flag) to clear, signalling BMC has
  * read the command.
@@ -1111,3 +1151,30 @@
 
   return (0);
 }
+
+int
+ipmi_kcs_wait (ipmi_kcs_ctx_t ctx)
+{
+  if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC)
+    {
+      ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx));
+      return (-1);
+    }
+
+  /* Block any threads waiting for events */
+  return (ipmi_mutex_lock(ctx->event_sem));
+}
+
+int
+ipmi_kcs_clear_wait (ipmi_kcs_ctx_t ctx)
+{
+  if (!ctx || ctx->magic != IPMI_KCS_CTX_MAGIC)
+    {
+      ERR_TRACE (ipmi_kcs_ctx_errormsg (ctx), ipmi_kcs_ctx_errnum (ctx));
+      return (-1);
+    }
+
+  /* Unlock any threads waiting on events */
+  return (ipmi_mutex_unlock(ctx->event_sem));
+}
+
diff -Naur freeipmi/libfreeipmi/src/driver/ipmi-semaphores.c freeipmi.mods/libfreeipmi/src/driver/ipmi-semaphores.c
--- freeipmi/libfreeipmi/src/driver/ipmi-semaphores.c	2010-02-05 17:53:06.000000000 -0700
+++ freeipmi.mods/libfreeipmi/src/driver/ipmi-semaphores.c	2010-02-23 09:10:51.000000000 -0700
@@ -45,19 +45,25 @@
 int
 ipmi_mutex_init (void)
 {
+    return ipmi_mutex_init_values(IPMI_INBAND_PROJ_ID, 1);
+}
+
+int
+ipmi_mutex_init_values (int proj_id, int initial_value)
+{
   int semid = -1;
   key_t key;
 
   /* Allocate Mutex */
 #ifndef NDEBUG
-  if ((key = ftok (IPMI_IPCKEY, IPMI_INBAND_PROJ_ID)) == ((key_t)-1))
+  if ((key = ftok (IPMI_IPCKEY, proj_id)) == ((key_t)-1))
     /* When doing development out of the source code tree, the
      * IPCKEY file may not yet exist, so we do a hack to get it to
      * work.  This is only when we work in debug mode.
      */
     key = ftok (IPMI_DEBUG_IPCKEY, IPMI_INBAND_DEBUG_PROJ_ID);
 #else /* !NDEBUG */
-  if ((key = ftok (IPMI_IPCKEY, IPMI_INBAND_PROJ_ID)) == ((key_t)-1))
+  if ((key = ftok (IPMI_IPCKEY, proj_id)) == ((key_t)-1))
     {
       ERRNO_TRACE (errno);
       return (-1);
@@ -89,7 +95,7 @@
   {
     union semun mutex_init;
     unsigned short values[1];
-    values[0] = 1;
+    values[0] = initial_value;
     mutex_init.array = values;
     if (semctl (semid, 0, SETALL, mutex_init) < 0)
       {
@@ -145,3 +151,6 @@
   usleep (1);
   return (0);
 }
+
+
+
diff -Naur freeipmi/libfreeipmi/src/driver/ipmi-semaphores.h freeipmi.mods/libfreeipmi/src/driver/ipmi-semaphores.h
--- freeipmi/libfreeipmi/src/driver/ipmi-semaphores.h	2010-02-05 17:53:06.000000000 -0700
+++ freeipmi.mods/libfreeipmi/src/driver/ipmi-semaphores.h	2010-02-23 09:10:51.000000000 -0700
@@ -51,4 +51,6 @@
 
 int ipmi_mutex_unlock (int semid);
 
+int ipmi_mutex_init_values (int proj_id, int initial_value);
+
 #endif /* ipmi-semaphores.h */
