/*===========================================================================* * main * *===========================================================================*/ int main(int argc, char *argv[]) { message m_out; int r, ipc_status; size_t size; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); for (;;) { /* Wait for request. */ if(driver_receive(ANY, &m_in, &ipc_status) != OK) { panic("driver_receive failed"); } #if DEBUG2 printf("Filter: got request %d from %d\n", m_in.m_type, m_in.m_source); #endif if(m_in.m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) { ds_event(); continue; } who_e = m_in.m_source; req_id = m_in.BDEV_ID; grant_id = m_in.BDEV_GRANT; size = 0; /* Forword the request message to the drivers. */ switch(m_in.m_type) { case BDEV_OPEN: /* open/close is a noop for filter. */ case BDEV_CLOSE: r = OK; break; case BDEV_READ: r = do_rdwt(FLT_READ); break; case BDEV_WRITE: r = do_rdwt(FLT_WRITE); break; case BDEV_GATHER: r = do_vrdwt(FLT_READ); break; case BDEV_SCATTER: r = do_vrdwt(FLT_WRITE); break; case BDEV_IOCTL: r = do_ioctl(&m_in); break; default: printf("Filter: ignoring unknown request %d from %d\n", m_in.m_type, m_in.m_source); continue; } #if DEBUG2 printf("Filter: replying with code %d\n", r); #endif /* Send back reply message. */ m_out.m_type = BDEV_REPLY; m_out.BDEV_ID = req_id; m_out.BDEV_STATUS = r; send(who_e, &m_out); } return 0; }
/*===========================================================================* * floppy_task * *===========================================================================*/ PUBLIC floppy_task() { /* Main program of the floppy disk driver task. */ int r, caller, proc_nr; /* Here is the main loop of the disk task. It waits for a message, carries * it out, and sends a reply. */ while (TRUE) { /* First wait for a request to read or write a disk block. */ receive(ANY, &mess); /* get a request to do some work */ if (mess.m_source < 0) panic("disk task got message from ", mess.m_source); caller = mess.m_source; proc_nr = mess.PROC_NR; /* Now carry out the work. */ switch(mess.m_type) { case DISK_READ: r = do_rdwt(&mess); break; case DISK_WRITE: r = do_rdwt(&mess); break; default: r = EINVAL; break; } /* Finally, prepare and send the reply message. */ mess.m_type = TASK_REPLY; mess.REP_PROC_NR = proc_nr; mess.REP_STATUS = r; /* # of bytes transferred or error code */ send(caller, &mess); /* send reply to caller */ } }
/*===========================================================================* * driver_task * *===========================================================================*/ PUBLIC void driver_task(void) { /* Main program of any device driver task. */ int r; message mess; /* Here is the main loop of the disk task. It waits for a message, carries * it out, and sends a reply. */ while (TRUE) { printf("CD: waiting for messages\n"); /* Wait for a request to read or write a disk block. */ if(receive(ANY, &mess) != OK) continue; device_caller = mess.m_source; proc_nr = mess.PROC_NR; printf("CD: message from %u, type %u\n",device_caller,proc_nr,mess.m_type); /* Now carry out the work. */ switch(mess.m_type) { case DEV_OPEN: case DEV_CLOSE: case CANCEL: case DEV_SELECT: /* forwards message to diskdriver and forwards response to caller*/ mess.m_source = thispid; /*make this the source*/ if(OK != sendrec(DRVR_PROC_NR, &mess)) panic("CryptcDrive","2 Message not sent back",s); printf("CD: waiting for diskdriver\n"); mess.m_source = thispid; /*make this the source*/ if(OK != send(device_caller, &mess)) panic("CryptDrive","3 Message not sent back",s); printf("CD: message to %u\n",device_caller); break; case DEV_IOCTL: doioctl(&mess); case DEV_READ: case DEV_WRITE: do_rdwt(&mess); break; case DEV_GATHER: case DEV_SCATTER: do_vrdwt(&mess); break; case HARD_INT: case SYS_SIG: case SYN_ALARM: break; /* don't reply */ } } }
/*===========================================================================* * 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; }
/*===========================================================================* * 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; }
/************************************************************************************************** * task_fs ************************************************************************************************** * <Ring 1> Main loop of Task FS. *************************************************************************************************/ PUBLIC void task_fs(){ init_fs(); while(TRUE){ send_recv(RECEIVE, ANY, &fs_msg); int src = fs_msg.source; pcaller = &proc_table[src]; switch(fs_msg.type){ case OPEN: fs_msg.FD = do_open(); break; case CLOSE: fs_msg.RETVAL = do_close(); break; case READ: case WRITE: fs_msg.CNT = do_rdwt(); break; case UNLINK: fs_msg.RETVAL = do_unlink(); break; case RESUME_PROC: src = fs_msg.PROC_NR; break; case FORK: fs_msg.RETVAL = fs_fork(); break; default: dump_msg("FS::unkown message:", &fs_msg); assert(0); break; } /* reply */ if(fs_msg.type != SUSPEND_PROC){ fs_msg.type = SYSCALL_RET; send_recv(SEND, src, &fs_msg); } } spin("FS"); }
/*===========================================================================* * floppy_task * *===========================================================================*/ PUBLIC void floppy_task() { register r, drive, caller, procno; /* * The main loop of the disk task. * It waits for a message, carries it out, and sends a reply. */ TRACE(printf("fd: task started\n")); dmagrab(FLOPPY, fdcint); dmawdat(FDC_CS, IRUPT, FDC_DELAY); /* reset controller */ dmafree(FLOPPY); for (drive = 0; drive < NR_FLOPDRIVES; drive++) curcyl[drive] = -1; /* uncalibrated */ while (TRUE) { receive(ANY, &mess); ASSERT(mess.m_source >= 0); TRACE(printf("fd: received %d from %d\n",mess.m_type,mess.m_source)); caller = mess.m_source; procno = mess.PROC_NR; /* Now carry out the work. */ switch (mess.m_type) { case DISK_READ: case DISK_WRITE: r = do_rdwt(&mess); break; case SCATTERED_IO: r = do_vrdwt(&mess, do_rdwt); break; default: r = EINVAL; break; } /* Finally, prepare and send the reply message. */ mess.m_type = TASK_REPLY; mess.REP_PROC_NR = procno; mess.REP_STATUS = r; /* # of bytes transferred or error code */ send(caller, &mess); /* send reply to caller */ } }
/*===========================================================================* * 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); }
/** * <Ring 1> The main loop of TASK FS. * *****************************************************************************/ PUBLIC void task_fs() { printl("{FS} Task FS begins.\n"); init_fs(); while (1) { send_recv(RECEIVE, ANY, &fs_msg); int msgtype = fs_msg.type; int src = fs_msg.source; pcaller = &proc_table[src]; switch (msgtype) { case OPEN: fs_msg.FD = do_open(); break; case CLOSE: fs_msg.RETVAL = do_close(); break; case READ: case WRITE: fs_msg.CNT = do_rdwt(); break; case UNLINK: fs_msg.RETVAL = do_unlink(); break; case RESUME_PROC: src = fs_msg.PROC_NR; break; case FORK: fs_msg.RETVAL = fs_fork(); break; case EXIT: fs_msg.RETVAL = fs_exit(); break; /* case LSEEK: */ /* fs_msg.OFFSET = do_lseek(); */ /* break; */ case STAT: fs_msg.RETVAL = do_stat(); break; default: dump_msg("FS::unknown message:", &fs_msg); assert(0); break; } #ifdef ENABLE_DISK_LOG char * msg_name[128]; msg_name[OPEN] = "OPEN"; msg_name[CLOSE] = "CLOSE"; msg_name[READ] = "READ"; msg_name[WRITE] = "WRITE"; msg_name[LSEEK] = "LSEEK"; msg_name[UNLINK] = "UNLINK"; /* msg_name[FORK] = "FORK"; */ /* msg_name[EXIT] = "EXIT"; */ /* msg_name[STAT] = "STAT"; */ switch (msgtype) { case UNLINK: dump_fd_graph("%s just finished. (pid:%d)", msg_name[msgtype], src); //panic(""); case OPEN: case CLOSE: case READ: case WRITE: case FORK: case EXIT: /* case LSEEK: */ case STAT: break; case RESUME_PROC: break; default: assert(0); } #endif /* reply */ if (fs_msg.type != SUSPEND_PROC) { fs_msg.type = SYSCALL_RET; send_recv(SEND, src, &fs_msg); } } }
PUBLIC void task_fs() { printl("Task FS begins.\n"); init_fs(); while (1) { send_recv(RECEIVE, ANY, &fs_msg); int src = fs_msg.source; pcaller = &proc_table[src]; switch (fs_msg.type) { case OPEN: fs_msg.FD = do_open(); break; case CLOSE: fs_msg.RETVAL = do_close(); break; case READ: case WRITE: fs_msg.CNT = do_rdwt(); break; case UNLINK: fs_msg.RETVAL = do_unlink(); break; case RESUME_PROC: src = fs_msg.PROC_NR; // 恢复最初请求的进程,如 TestB break; case FORK: fs_msg.RETVAL = fs_fork(); break; case EXIT: fs_msg.RETVAL = fs_exit(); break; case STAT: fs_msg.RETVAL = do_stat(); break; default: dump_msg("FS::unknown message:", &fs_msg); assert(0); break; } /* 如果发送者要求挂起,则不回送消息 */ if (fs_msg.type != SUSPEND_PROC) { fs_msg.type = SYSCALL_RET; send_recv(SEND, src, &fs_msg); } } spin("FS"); }