protocol: Provide abstraction over event notification

How this works will be transport-dependent. Move the event notification
helpers into the protocol abstraction and call-back through the
registered flush handler as necessary.

Change-Id: I29e3a9a9785b92de46a2b2750257fb7f8480a184
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/control.c b/control.c
index c9956e9..01a2e5f 100644
--- a/control.c
+++ b/control.c
@@ -47,7 +47,7 @@
 	 * mapping back to flash, or memory in case we're using a virtual pnor.
 	 * Better set the bmc event to notify the host of this.
 	 */
-	windows_reset_all(context, SET_BMC_EVENT);
+	windows_reset_all(context, EVENT_TRIGGER);
 	rc = lpc_reset(context);
 	if (rc < 0) {
 		return rc;
@@ -71,7 +71,7 @@
 	flash_set_bytemap(context, 0, context->flash_size, FLASH_DIRTY);
 
 	/* Force daemon to reload all windows -> Set BMC event to notify host */
-	windows_reset_all(context, SET_BMC_EVENT);
+	windows_reset_all(context, EVENT_TRIGGER);
 
 	return 0;
 }
@@ -86,7 +86,7 @@
 	}
 
 	/* Nothing to check - Just set the bit to notify the host */
-	rc = set_bmc_events(context, BMC_EVENT_FLASH_CTRL_LOST, SET_BMC_EVENT);
+	rc = protocol_events_set(context, BMC_EVENT_FLASH_CTRL_LOST, EVENT_TRIGGER);
 	if (rc < 0) {
 		return rc;
 	}
@@ -111,7 +111,7 @@
 	}
 
 	/* Clear the bit and send the BMC Event to the host */
-	rc = clr_bmc_events(context, BMC_EVENT_FLASH_CTRL_LOST, SET_BMC_EVENT);
+	rc = protocol_events_clear(context, BMC_EVENT_FLASH_CTRL_LOST, EVENT_TRIGGER);
 	if (rc < 0) {
 		return rc;
 	}
diff --git a/mbox.h b/mbox.h
index 3676825..c2db30c 100644
--- a/mbox.h
+++ b/mbox.h
@@ -10,6 +10,7 @@
 #include <stdbool.h>
 
 #include "protocol.h"
+#include "transport.h"
 #include "vpnor/mboxd_pnor_partition_table.h"
 
 enum api_version {
@@ -134,12 +135,10 @@
 
 struct mbox_context;
 
-typedef int (*mboxd_mbox_handler)(struct mbox_context *, union mbox_regs *,
-				  struct mbox_msg *);
-
 struct mbox_context {
 	enum api_version version;
 	const struct protocol_ops *protocol;
+	const struct transport_ops *transport;
 
 /* System State */
 	enum mbox_state state;
@@ -149,9 +148,6 @@
 	uint8_t bmc_events;
 	uint8_t prev_seq;
 
-/* Command Dispatch */
-	const mboxd_mbox_handler *handlers;
-
 /* Window State */
 	/* The window list struct containing all current "windows" */
 	struct window_list windows;
diff --git a/mboxd.c b/mboxd.c
index 2382724..a5c7ef6 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -139,7 +139,7 @@
 				break;
 			case SIGHUP:
 				/* Host didn't request reset -> Notify it */
-				windows_reset_all(context, SET_BMC_EVENT);
+				windows_reset_all(context, EVENT_TRIGGER);
 				rc = lpc_reset(context);
 				if (rc < 0) {
 					MSG_ERR("WARNING: Failed to point the "
@@ -177,7 +177,7 @@
 
 	/* Best to reset windows and the lpc mapping for safety */
 	/* Host didn't request reset -> Notify it */
-	windows_reset_all(context, SET_BMC_EVENT);
+	windows_reset_all(context, EVENT_TRIGGER);
 	rc = lpc_reset(context);
 	/* Not much we can do if this fails */
 	if (rc < 0) {
@@ -394,7 +394,7 @@
 		MSG_ERR("LPC configuration failed, RESET required: %d\n", rc);
 	}
 
-	rc = set_bmc_events(context, BMC_EVENT_DAEMON_READY, SET_BMC_EVENT);
+	rc = protocol_events_set(context, BMC_EVENT_DAEMON_READY, EVENT_TRIGGER);
 	if (rc) {
 		goto finish;
 	}
@@ -406,7 +406,7 @@
 
 finish:
 	MSG_INFO("Daemon Exiting...\n");
-	clr_bmc_events(context, BMC_EVENT_DAEMON_READY, SET_BMC_EVENT);
+	protocol_events_clear(context, BMC_EVENT_DAEMON_READY, EVENT_TRIGGER);
 
 #ifdef VIRTUAL_PNOR_ENABLED
 	destroy_vpnor(context);
diff --git a/protocol.c b/protocol.c
index 4160e6e..c18083f 100644
--- a/protocol.c
+++ b/protocol.c
@@ -5,16 +5,61 @@
 #include <errno.h>
 #include <stdint.h>
 
+#include "common.h"
 #include "flash.h"
 #include "mbox.h"
 #include "lpc.h"
-#include "transport_mbox.h" /* TODO: Remove dependency on transport_mbox.h */
 #include "windows.h"
 
+/*
+ * protocol_events_set() - Set BMC events
+ * @context:	The mbox context pointer
+ * @bmc_event:	The bits to set
+ * @write_back:	Whether to write back to the register -> will interrupt host
+ *
+ * Return:	0 on success otherwise negative error code
+ */
+int protocol_events_set(struct mbox_context *context, uint8_t bmc_event,
+		   bool write_back)
+{
+	uint8_t mask = 0x00;
+
+	switch (context->version) {
+	case API_VERSION_1:
+		mask = BMC_EVENT_V1_MASK;
+		break;
+	default:
+		mask = BMC_EVENT_V2_MASK;
+		break;
+	}
+
+	context->bmc_events |= (bmc_event & mask);
+	MSG_DBG("BMC Events set to: 0x%.2x\n", context->bmc_events);
+
+	return write_back ? context->transport->flush_events(context) : 0;
+}
+
+/*
+ * protocol_events_clear() - Clear BMC events
+ * @context:	The mbox context pointer
+ * @bmc_event:	The bits to clear
+ * @write_back:	Whether to write back to the register -> will interrupt host
+ *
+ * Return:	0 on success otherwise negative error code
+ */
+int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event,
+		   bool write_back)
+{
+	context->bmc_events &= ~bmc_event;
+	MSG_DBG("BMC Events clear to: 0x%.2x\n", context->bmc_events);
+
+	return write_back ? context->transport->flush_events(context) : 0;
+}
+
 int protocol_v1_reset(struct mbox_context *context)
 {
 	/* Host requested it -> No BMC Event */
-	windows_reset_all(context, NO_BMC_EVENT);
+	windows_reset_all(context, EVENT_SUPPRESS);
 	return lpc_reset(context);
 }
 
@@ -31,7 +76,7 @@
 
 	/* Do the {up,down}grade if necessary*/
 	if (rc != old_version) {
-		windows_reset_all(context, SET_BMC_EVENT);
+		windows_reset_all(context, EVENT_TRIGGER);
 		return context->protocol->get_info(context, io);
 	}
 
@@ -104,7 +149,7 @@
 				return rc;
 			}
 		}
-		windows_close_current(context, NO_BMC_EVENT, FLAGS_NONE);
+		windows_close_current(context, EVENT_SUPPRESS, FLAGS_NONE);
 	}
 
 	/* Offset the host has requested */
@@ -284,15 +329,15 @@
 	}
 
 	/* Host asked for it -> Don't set the BMC Event */
-	windows_close_current(context, NO_BMC_EVENT, io->req.flags);
+	windows_close_current(context, EVENT_SUPPRESS, io->req.flags);
 
 	return 0;
 }
 
 int protocol_v1_ack(struct mbox_context *context, struct protocol_ack *io)
 {
-	return clr_bmc_events(context, (io->req.flags & BMC_EVENT_ACK_MASK),
-			      SET_BMC_EVENT);
+	return protocol_events_clear(context, (io->req.flags & BMC_EVENT_ACK_MASK),
+			      EVENT_TRIGGER);
 }
 
 /*
@@ -327,7 +372,7 @@
 
 	/* Do the {up,down}grade if necessary*/
 	if (rc != old_version) {
-		windows_reset_all(context, SET_BMC_EVENT);
+		windows_reset_all(context, EVENT_TRIGGER);
 		return context->protocol->get_info(context, io);
 	}
 
@@ -449,7 +494,7 @@
 	}
 
 	/* Host asked for it -> Don't set the BMC Event */
-	windows_close_current(context, NO_BMC_EVENT, io->req.flags);
+	windows_close_current(context, EVENT_SUPPRESS, io->req.flags);
 
 	return 0;
 }
diff --git a/protocol.h b/protocol.h
index 5cdc2eb..f2b8e6f 100644
--- a/protocol.h
+++ b/protocol.h
@@ -120,6 +120,14 @@
 
 int protocol_negotiate_version(struct mbox_context *context, uint8_t requested);
 
+#define EVENT_SUPPRESS		false
+#define EVENT_TRIGGER		true
+
+int protocol_events_set(struct mbox_context *context, uint8_t bmc_event,
+			bool write_back);
+int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event,
+			  bool write_back);
+
 /* Protocol v1 */
 int protocol_v1_reset(struct mbox_context *context);
 int protocol_v1_get_info(struct mbox_context *context,
diff --git a/test/bmc_event_ack_v2.c b/test/bmc_event_ack_v2.c
index 3bf1f37..c9056de 100644
--- a/test/bmc_event_ack_v2.c
+++ b/test/bmc_event_ack_v2.c
@@ -49,7 +49,7 @@
 	rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
 	assert(rc == 1);
 
-	set_bmc_events(ctx, FLAGS, SET_BMC_EVENT);
+	protocol_events_set(ctx, FLAGS, EVENT_TRIGGER);
 
 	rc = mbox_command_dispatch(ctx, command, sizeof(command));
 	assert(rc == 1);
diff --git a/transport.h b/transport.h
new file mode 100644
index 0000000..d6ec39e
--- /dev/null
+++ b/transport.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* Copyright (C) 2018 IBM Corp. */
+
+#ifndef TRANSPORT_H
+#define TRANSPORT_H
+
+#include "mbox.h"
+
+struct transport_ops {
+	int (*flush_events)(struct mbox_context *context);
+};
+
+#endif /* TRANSPORT_H */
diff --git a/transport_mbox.c b/transport_mbox.c
index fcc4430..fb4c28a 100644
--- a/transport_mbox.c
+++ b/transport_mbox.c
@@ -84,12 +84,13 @@
 }
 
 /*
- * write_bmc_event_reg() - Write to the BMC controlled status register (reg 15)
+ * transport_mbox_flush_events() - Write to the BMC controlled status register
+ * 				   (reg 15)
  * @context:	The mbox context pointer
  *
  * Return:	0 on success otherwise negative error code
  */
-static int write_bmc_event_reg(struct mbox_context *context)
+static int transport_mbox_flush_events(struct mbox_context *context)
 {
 	int rc;
 
@@ -98,7 +99,7 @@
 	if (rc != MBOX_BMC_EVENT) {
 		MSG_ERR("Couldn't lseek mbox to byte %d: %s\n", MBOX_BMC_EVENT,
 				strerror(errno));
-		return -MBOX_R_SYSTEM_ERROR;
+		return -errno;
 	}
 
 	/* Write to mbox status register */
@@ -106,7 +107,7 @@
 	if (rc != 1) {
 		MSG_ERR("Couldn't write to BMC status reg: %s\n",
 				strerror(errno));
-		return -MBOX_R_SYSTEM_ERROR;
+		return -errno;
 	}
 
 	/* Reset to start */
@@ -114,57 +115,12 @@
 	if (rc) {
 		MSG_ERR("Couldn't reset MBOX offset to zero: %s\n",
 				strerror(errno));
-		return -MBOX_R_SYSTEM_ERROR;
+		return -errno;
 	}
 
 	return 0;
 }
 
-/*
- * set_bmc_events() - Set BMC events
- * @context:	The mbox context pointer
- * @bmc_event:	The bits to set
- * @write_back:	Whether to write back to the register -> will interrupt host
- *
- * Return:	0 on success otherwise negative error code
- */
-int set_bmc_events(struct mbox_context *context, uint8_t bmc_event,
-		   bool write_back)
-{
-	uint8_t mask = 0x00;
-
-	switch (context->version) {
-	case API_VERSION_1:
-		mask = BMC_EVENT_V1_MASK;
-		break;
-	default:
-		mask = BMC_EVENT_V2_MASK;
-		break;
-	}
-
-	context->bmc_events |= (bmc_event & mask);
-	MSG_DBG("BMC Events set to: 0x%.2x\n", context->bmc_events);
-
-	return write_back ? write_bmc_event_reg(context) : 0;
-}
-
-/*
- * clr_bmc_events() - Clear BMC events
- * @context:	The mbox context pointer
- * @bmc_event:	The bits to clear
- * @write_back:	Whether to write back to the register -> will interrupt host
- *
- * Return:	0 on success otherwise negative error code
- */
-int clr_bmc_events(struct mbox_context *context, uint8_t bmc_event,
-		   bool write_back)
-{
-	context->bmc_events &= ~bmc_event;
-	MSG_DBG("BMC Events clear to: 0x%.2x\n", context->bmc_events);
-
-	return write_back ? write_bmc_event_reg(context) : 0;
-}
-
 /* Command Handlers */
 
 /*
@@ -532,7 +488,10 @@
 	return 0;
 }
 
-static const mboxd_mbox_handler mbox_handlers[] = {
+typedef int (*mboxd_mbox_handler)(struct mbox_context *, union mbox_regs *,
+				  struct mbox_msg *);
+
+static const mboxd_mbox_handler transport_mbox_handlers[] = {
 	mbox_handle_reset,
 	mbox_handle_mbox_info,
 	mbox_handle_flash_info,
@@ -565,9 +524,11 @@
 	MSG_INFO("Received MBOX command: %u\n", req->msg.command);
 	rc = check_req_valid(context, req);
 	if (!rc) {
+		mboxd_mbox_handler handler;
+
 		/* Commands start at 1 so we have to subtract 1 from the cmd */
-		mboxd_mbox_handler h = context->handlers[req->msg.command - 1];
-		rc = h(context, req, &resp);
+		handler = transport_mbox_handlers[req->msg.command - 1];
+		rc = handler(context, req, &resp);
 		if (rc < 0) {
 			MSG_ERR("Error handling mbox cmd: %d\n",
 				req->msg.command);
@@ -645,11 +606,15 @@
 	return handle_mbox_req(context, &req);
 }
 
+static const struct transport_ops transport_mbox_ops = {
+	.flush_events = transport_mbox_flush_events,
+};
+
 int __init_mbox_dev(struct mbox_context *context, const char *path)
 {
 	int fd;
 
-	context->handlers = mbox_handlers;
+	context->transport = &transport_mbox_ops;
 
 	/* Open MBOX Device */
 	fd = open(path, O_RDWR | O_NONBLOCK);
diff --git a/transport_mbox.h b/transport_mbox.h
index 8f65f7d..4c2952c 100644
--- a/transport_mbox.h
+++ b/transport_mbox.h
@@ -7,13 +7,6 @@
 #include "common.h"
 #include "mbox.h"
 
-#define NO_BMC_EVENT			false
-#define SET_BMC_EVENT			true
-
-int set_bmc_events(struct mbox_context *context, uint8_t bmc_event,
-		   bool write_back);
-int clr_bmc_events(struct mbox_context *context, uint8_t bmc_event,
-		   bool write_back);
 int dispatch_mbox(struct mbox_context *context);
 int init_mbox_dev(struct mbox_context *context);
 void free_mbox_dev(struct mbox_context *context);
diff --git a/windows.c b/windows.c
index a126365..b56f73f 100644
--- a/windows.c
+++ b/windows.c
@@ -394,7 +394,7 @@
 	MSG_DBG("Close current window, flags: 0x%.2x\n", flags);
 
 	if (set_bmc_event) {
-		set_bmc_events(context, BMC_EVENT_WINDOW_RESET, SET_BMC_EVENT);
+		protocol_events_set(context, BMC_EVENT_WINDOW_RESET, EVENT_TRIGGER);
 	}
 
 	if (flags & FLAGS_SHORT_LIFETIME) {