Esempio n. 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;
}
Esempio n. 2
0
/*===========================================================================*
 *				   main 				     *
 *===========================================================================*/
int main(void)
{
  message msg;
  int r, ipc_status;

  /* SEF local startup. */
  sef_local_startup();

  /* The receive loop. */
  for (;;) {
	if ((r = driver_receive(ANY, &msg, &ipc_status)) != OK)
		panic("memory: driver_receive failed (%d)", r);

	if (IS_BDEV_RQ(msg.m_type))
		blockdriver_process(&m_bdtab, &msg, ipc_status);
	else
		chardriver_process(&m_cdtab, CHARDRIVER_SYNC, &msg,
			ipc_status);
  }

  return(OK);
}
Esempio n. 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);
}