lib/libblockdriver/driver_st.c
/* This file contains the singlethreaded device driver interface.
 *
 * Changes:
 *   Aug 27, 2011   extracted from driver.c (A. Welzel)
 *
 * The entry points into this file are:
 *   blockdriver_task:		the main message loop of the driver
 *   blockdriver_terminate:	break out of the main message loop
 *   blockdriver_handle_msg:	handle a single received message
 *   blockdriver_receive_mq:	message receive interface with message queueing
 *   blockdriver_mq_queue:	queue an incoming message for later processing
 */

#include <minix/drivers.h>
#include <minix/blockdriver.h>

#include "const.h"
#include "driver.h"
#include "mq.h"

static int running;

/*===========================================================================*
 *			       blockdriver_receive_mq			     *
 *===========================================================================*/
int blockdriver_receive_mq(message *m_ptr, int *status_ptr)
{
/* receive() interface for drivers with message queueing. */

  /* Any queued messages? */
  if (mq_dequeue(SINGLE_THREAD, m_ptr, status_ptr))
	return OK;

  /* Fall back to standard receive() interface otherwise. */
  return driver_receive(ANY, m_ptr, status_ptr);
}

/*===========================================================================*
 *				blockdriver_terminate			     *
 *===========================================================================*/
void blockdriver_terminate(void)
{
/* Break out of the main driver loop after finishing the current request. */

  running = FALSE;
}

/*===========================================================================*
 *				blockdriver_task			     *
 *===========================================================================*/
void blockdriver_task(struct blockdriver *bdp)
{
/* Main program of any block device driver task. */
  int r, ipc_status;
  message mess;

  running = TRUE;

  /* Here is the main loop of the disk task.  It waits for a message, carries
   * it out, and sends a reply.
   */
  while (running) {
	if ((r = blockdriver_receive_mq(&mess, &ipc_status)) != OK)
		panic("blockdriver_receive_mq failed: %d", r);

	blockdriver_process(bdp, &mess, ipc_status);
  }
}

/*===========================================================================*
 *				blockdriver_process			     *
 *===========================================================================*/
void blockdriver_process(struct blockdriver *bdp, message *m_ptr,
  int ipc_status)
{
/* Handle the given received message. */
  int r;

  /* Process the notification or request. */
  if (is_ipc_notify(ipc_status)) {
	blockdriver_handle_notify(bdp, m_ptr);

	/* Do not reply to notifications. */
  } else {
	r = blockdriver_handle_request(bdp, m_ptr, SINGLE_THREAD);

	blockdriver_reply(m_ptr, ipc_status, r);
  }
}

/*===========================================================================*
 *				blockdriver_mq_queue			     *
 *===========================================================================*/
int blockdriver_mq_queue(message *m, int status)
{
/* Queue a message for later processing. */

  return mq_enqueue(SINGLE_THREAD, m, status);
}
