📄 device.c
字号:
struct filp *f; register struct inode *rip; dev_t dev; if ( (f = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code); rip = f->filp_ino; /* get inode pointer */ if ( (rip->i_mode & I_TYPE) != I_CHAR_SPECIAL && (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY); dev = (dev_t) rip->i_zone[0];#if ENABLE_BINCOMPAT if ((m_in.TTY_REQUEST >> 8) == 't') { /* Obsolete sgtty ioctl, message contains more than is sane. */ struct dmap *dp; message dev_mess; dp = &dmap[(dev >> MAJOR) & BYTE]; dev_mess = m; /* Copy full message with all the weird bits. */ dev_mess.m_type = DEV_IOCTL; dev_mess.PROC_NR = who; dev_mess.TTY_LINE = (dev >> MINOR) & BYTE; /* Call the task. */ (*dp->dmap_io)(dp->dmap_driver, &dev_mess); m_out.TTY_SPEK = dev_mess.TTY_SPEK; /* erase and kill */ m_out.TTY_FLAGS = dev_mess.TTY_FLAGS; /* flags */ return(dev_mess.REP_STATUS); }#endif return(dev_io(DEV_IOCTL, dev, who, m_in.ADDRESS, 0L, m_in.REQUEST, f->filp_flags));}/*===========================================================================* * gen_io * *===========================================================================*/PUBLIC void gen_io(task_nr, mess_ptr)int task_nr; /* which task to call */message *mess_ptr; /* pointer to message for task */{/* All file system I/O ultimately comes down to I/O on major/minor device * pairs. These lead to calls on the following routines via the dmap table. */ int r, proc_nr; message local_m; proc_nr = mess_ptr->PROC_NR; if (! isokprocnr(proc_nr)) { printf("FS: warning, got illegal process number (%d) from %d\n", mess_ptr->PROC_NR, mess_ptr->m_source); return; } while ((r = sendrec(task_nr, mess_ptr)) == ELOCKED) { /* sendrec() failed to avoid deadlock. The task 'task_nr' is * trying to send a REVIVE message for an earlier request. * Handle it and go try again. */ if ((r = receive(task_nr, &local_m)) != OK) { break; } /* If we're trying to send a cancel message to a task which has just * sent a completion reply, ignore the reply and abort the cancel * request. The caller will do the revive for the process. */ if (mess_ptr->m_type == CANCEL && local_m.REP_PROC_NR == proc_nr) { return; } /* Otherwise it should be a REVIVE. */ if (local_m.m_type != REVIVE) { printf( "fs: strange device reply from %d, type = %d, proc = %d (1)\n", local_m.m_source, local_m.m_type, local_m.REP_PROC_NR); continue; } revive(local_m.REP_PROC_NR, local_m.REP_STATUS); } /* The message received may be a reply to this call, or a REVIVE for some * other process. */ for (;;) { if (r != OK) { if (r == EDEADSRCDST) return; /* give up */ if (r == EDSTDIED) return; if (r == ESRCDIED) return; if (r == ELOCKED) return; else panic(__FILE__,"call_task: can't send/receive", r); } /* Did the process we did the sendrec() for get a result? */ if (mess_ptr->REP_PROC_NR == proc_nr) { break; } else if (mess_ptr->m_type == REVIVE) { /* Otherwise it should be a REVIVE. */ revive(mess_ptr->REP_PROC_NR, mess_ptr->REP_STATUS); } else { printf( "fs: strange device reply from %d, type = %d, proc = %d (2)\n", mess_ptr->m_source, mess_ptr->m_type, mess_ptr->REP_PROC_NR); return; } r = receive(task_nr, mess_ptr); }}/*===========================================================================* * ctty_io * *===========================================================================*/PUBLIC void ctty_io(task_nr, mess_ptr)int task_nr; /* not used - for compatibility with dmap_t */message *mess_ptr; /* pointer to message for task */{/* This routine is only called for one device, namely /dev/tty. Its job * is to change the message to use the controlling terminal, instead of the * major/minor pair for /dev/tty itself. */ struct dmap *dp; if (fp->fp_tty == 0) { /* No controlling tty present anymore, return an I/O error. */ mess_ptr->REP_STATUS = EIO; } else { /* Substitute the controlling terminal device. */ dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE]; mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE; (*dp->dmap_io)(dp->dmap_driver, mess_ptr); }}/*===========================================================================* * no_dev * *===========================================================================*/PUBLIC int no_dev(op, dev, proc, flags)int op; /* operation, DEV_OPEN or DEV_CLOSE */dev_t dev; /* device to open or close */int proc; /* process to open/close for */int flags; /* mode bits and flags */{/* Called when opening a nonexistent device. */ return(ENODEV);}/*===========================================================================* * no_dev_io * *===========================================================================*/PUBLIC void no_dev_io(int proc, message *m){/* Called when doing i/o on a nonexistent device. */ return;}/*===========================================================================* * clone_opcl * *===========================================================================*/PUBLIC int clone_opcl(op, dev, proc, flags)int op; /* operation, DEV_OPEN or DEV_CLOSE */dev_t dev; /* device to open or close */int proc; /* process to open/close for */int flags; /* mode bits and flags */{/* Some devices need special processing upon open. Such a device is "cloned", * i.e. on a succesful open it is replaced by a new device with a new unique * minor device number. This new device number identifies a new object (such * as a new network connection) that has been allocated within a task. */ struct dmap *dp; int minor; message dev_mess; /* Determine task dmap. */ dp = &dmap[(dev >> MAJOR) & BYTE]; minor = (dev >> MINOR) & BYTE; dev_mess.m_type = op; dev_mess.DEVICE = minor; dev_mess.PROC_NR = proc; dev_mess.COUNT = flags; /* Call the task. */ (*dp->dmap_io)(dp->dmap_driver, &dev_mess); if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) { if (dev_mess.REP_STATUS != minor) { /* A new minor device number has been returned. Create a * temporary device file to hold it. */ struct inode *ip; /* Device number of the new device. */ dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR); ip = alloc_inode(root_dev, ALL_MODES | I_CHAR_SPECIAL); if (ip == NIL_INODE) { /* Oops, that didn't work. Undo open. */ (void) clone_opcl(DEV_CLOSE, dev, proc, 0); return(err_code); } ip->i_zone[0] = dev; put_inode(fp->fp_filp[m_in.fd]->filp_ino); fp->fp_filp[m_in.fd]->filp_ino = ip; } dev_mess.REP_STATUS = OK; } return(dev_mess.REP_STATUS);}/*===========================================================================* * dev_up * *===========================================================================*/PUBLIC void dev_up(int maj){ /* A new device driver has been mapped in. This function * checks if any filesystems are mounted on it, and if so, * dev_open()s them so the filesystem can be reused. */ struct super_block *sb; struct filp *fp; int r; /* Open a device once for every filp that's opened on it, * and once for every filesystem mounted from it. */ for(sb = super_block; sb < &super_block[NR_SUPERS]; sb++) { int minor; if(sb->s_dev == NO_DEV) continue; if(((sb->s_dev >> MAJOR) & BYTE) != maj) continue; minor = ((sb->s_dev >> MINOR) & BYTE); printf("FS: remounting dev %d/%d\n", maj, minor); if((r = dev_open(sb->s_dev, FS_PROC_NR, sb->s_rd_only ? R_BIT : (R_BIT|W_BIT))) != OK) { printf("FS: mounted dev %d/%d re-open failed: %d.\n", maj, minor, r); } } for(fp = filp; fp < &filp[NR_FILPS]; fp++) { struct inode *in; int minor; if(fp->filp_count < 1 || !(in=fp->filp_ino)) continue; if(((in->i_zone[0] >> MAJOR) & BYTE) != maj) continue; if(!(in->i_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue; minor = ((in->i_zone[0] >> MINOR) & BYTE); if((r = dev_open(in->i_dev, FS_PROC_NR, in->i_mode & (R_BIT|W_BIT))) != OK) { printf("FS: file on dev %d/%d re-open failed: %d.\n", maj, minor, r); } } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -