/*===========================================================================* * blockdriver_process * *===========================================================================*/ PUBLIC 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_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); }