Beispiel #1
0
/*===========================================================================*
 *				blockdriver_handle_request		     *
 *===========================================================================*/
int blockdriver_handle_request(struct blockdriver *bdp, message *m_ptr,
	thread_id_t id)
{
/* Call the appropiate driver function, based on the type of request. Return
 * the result code that is to be sent back to the caller, or EDONTREPLY if no
 * reply is to be sent.
 */
  int r;

  /* We might get spurious requests if the driver has been restarted. Deny any
   * requests on devices that have not previously been opened, signaling the
   * caller that something went wrong.
   */
  if (IS_BDEV_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->BDEV_MINOR)) {
	/* Reply ERESTART to spurious requests for unopened devices. */
	if (m_ptr->m_type != BDEV_OPEN)
		return ERESTART;

	/* Mark the device as opened otherwise. */
	set_open_dev(m_ptr->BDEV_MINOR);
  }

  trace_start(id, m_ptr);

  /* Call the appropriate function(s) for this request. */
  switch (m_ptr->m_type) {
  case BDEV_OPEN:	r = do_open(bdp, m_ptr);	break;
  case BDEV_CLOSE:	r = do_close(bdp, m_ptr);	break;
  case BDEV_READ:
  case BDEV_WRITE:	r = do_rdwt(bdp, m_ptr);	break;
  case BDEV_GATHER:
  case BDEV_SCATTER:	r = do_vrdwt(bdp, m_ptr, id);	break;
  case BDEV_IOCTL:	r = do_ioctl(bdp, m_ptr);	break;
  default:
	if (bdp->bdr_other)
		r = bdp->bdr_other(m_ptr);
	else
		r = EINVAL;
  }

  /* Let the driver perform any cleanup. */
  if (bdp->bdr_cleanup != NULL)
	(*bdp->bdr_cleanup)();

  trace_finish(id, r);

  return r;
}
Beispiel #2
0
/*===========================================================================*
 *				handle_request				     *
 *===========================================================================*/
static int handle_request(struct chardriver *cdp, message *m_ptr)
{
/* Call the appropiate driver function, based on the type of request. Return
 * the result code that is to be sent back to the caller, or EDONTREPLY if no
 * reply is to be sent.
 */
  int r;

  /* We might get spurious requests if the driver has been restarted. Deny any
   * requests on devices that have not previously been opened, signaling the
   * caller that something went wrong.
   */
  if (IS_CDEV_MINOR_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->DEVICE)) {
	/* Reply ERESTART to spurious requests for unopened devices. */
	if (m_ptr->m_type != DEV_OPEN)
		return ERESTART;

	/* Mark the device as opened otherwise. */
	set_open_dev(m_ptr->DEVICE);
  }

  /* Call the appropriate function(s) for this request. */
  switch (m_ptr->m_type) {
  case DEV_OPEN:	r = (*cdp->cdr_open)(m_ptr);	break;
  case DEV_CLOSE:	r = (*cdp->cdr_close)(m_ptr);	break;
  case DEV_IOCTL_S:	r = (*cdp->cdr_ioctl)(m_ptr);	break;
  case CANCEL:		r = (*cdp->cdr_cancel)(m_ptr);	break;
  case DEV_SELECT:	r = (*cdp->cdr_select)(m_ptr);	break;
  case DEV_READ_S:
  case DEV_WRITE_S:	r = do_rdwt(cdp, m_ptr);	break;
  case DEV_GATHER_S:
  case DEV_SCATTER_S:	r = do_vrdwt(cdp, m_ptr);	break;
  default:
	if (cdp->cdr_other)
		r = cdp->cdr_other(m_ptr);
	else
		r = EINVAL;
  }

  /* Let the driver perform any cleanup. */
  if (cdp->cdr_cleanup)
	(*cdp->cdr_cleanup)();

  return r;
}
Beispiel #3
0
/*===========================================================================*
 *				blockdriver_process_on_thread		     *
 *===========================================================================*/
void blockdriver_process_on_thread(struct blockdriver *bdp, message *m_ptr,
	int ipc_status, thread_id_t id)
{
/* Call the appropiate driver function, based on the type of request. Send
 * a result code to the caller. The call is processed in the context of the
 * given thread ID, which may be SINGLE_THREAD for single-threaded callers.
 */
  int r;

  /* Check for notifications first. We never reply to notifications. */
  if (is_ipc_notify(ipc_status)) {
	switch (_ENDPOINT_P(m_ptr->m_source)) {
	case HARDWARE:
		if (bdp->bdr_intr)
			(*bdp->bdr_intr)(m_ptr->m_notify.interrupts);
		break;

	case CLOCK:
		if (bdp->bdr_alarm)
			(*bdp->bdr_alarm)(m_ptr->m_notify.timestamp);
		break;

	default:
		if (bdp->bdr_other)
			(*bdp->bdr_other)(m_ptr, ipc_status);
	}

	return; /* do not send a reply */
  }

  /* Reply to character driver open requests with an error code. Otherwise, if
   * someone creates a character device node for a block driver, opening that
   * device node will cause the corresponding VFS thread to block forever.
   */
  if (m_ptr->m_type == CDEV_OPEN) {
	do_char_open(m_ptr, ipc_status);

	return;
  }

  /* We might get spurious requests if the driver has been restarted. Deny any
   * requests on devices that have not previously been opened, signaling the
   * caller that something went wrong.
   */
  if (IS_BDEV_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->m_lbdev_lblockdriver_msg.minor)) {
	/* Reply ERESTART to spurious requests for unopened devices. */
	if (m_ptr->m_type != BDEV_OPEN) {
		blockdriver_reply(m_ptr, ipc_status, ERESTART);

		return;
	}

	/* Mark the device as opened otherwise. */
	set_open_dev(m_ptr->m_lbdev_lblockdriver_msg.minor);
  }

  trace_start(id, m_ptr);

  /* Call the appropriate function(s) for this request. */
  switch (m_ptr->m_type) {
  case BDEV_OPEN:	r = do_open(bdp, m_ptr);	break;
  case BDEV_CLOSE:	r = do_close(bdp, m_ptr);	break;
  case BDEV_READ:
  case BDEV_WRITE:	r = do_rdwt(bdp, m_ptr);	break;
  case BDEV_GATHER:
  case BDEV_SCATTER:	r = do_vrdwt(bdp, m_ptr, id);	break;
  case BDEV_IOCTL:	r = do_ioctl(bdp, m_ptr);	break;
  default:
	if (bdp->bdr_other != NULL)
		(*bdp->bdr_other)(m_ptr, ipc_status);

	return;	/* do not send a reply */
  }

  /* Let the driver perform any cleanup. */
  if (bdp->bdr_cleanup != NULL)
	(*bdp->bdr_cleanup)();

  trace_finish(id, r);

  blockdriver_reply(m_ptr, ipc_status, r);
}