diff --git a/kernel/console.c b/kernel/console.c index b20d4a9..736d96a 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -156,20 +156,18 @@ struct { #define C(x) ((x)-'@') // Contro int -consoleread(struct inode *ip, int user_dst, uint64 dst, int n) +consoleread(int user_dst, uint64 dst, int n) { uint target; int c; char buf[1]; - iunlock(ip); target = n; acquire(&cons.lock); while(n > 0){ while(input.r == input.w){ if(myproc()->killed){ release(&cons.lock); - ilock(ip); return -1; } sleep(&input.r, &cons.lock); @@ -192,17 +190,15 @@ consoleread(struct inode *ip, int user_dst, uint64 dst, int n) break; } release(&cons.lock); - ilock(ip); return target - n; } int -consolewrite(struct inode *ip, int user_src, uint64 src, int n) +consolewrite(int user_src, uint64 src, int n) { int i; - iunlock(ip); acquire(&cons.lock); for(i = 0; i < n; i++){ char c; @@ -211,7 +207,6 @@ consolewrite(struct inode *ip, int user_src, uint64 src, int n) consputc(c); } release(&cons.lock); - ilock(ip); return n; } diff --git a/kernel/file.c b/kernel/file.c index 6f27f22..f330cf1 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -73,9 +73,9 @@ fileclose(struct file *f) f->type = FD_NONE; release(&ftable.lock); - if(ff.type == FD_PIPE) + if(ff.type == FD_PIPE){ pipeclose(ff.pipe, ff.writable); - else if(ff.type == FD_INODE){ + } else if(ff.type == FD_INODE || ff.type == FD_DEVICE){ begin_op(); iput(ff.ip); end_op(); @@ -90,7 +90,7 @@ filestat(struct file *f, uint64 addr) struct proc *p = myproc(); struct stat st; - if(f->type == FD_INODE){ + if(f->type == FD_INODE || f->type == FD_DEVICE){ ilock(f->ip); stati(f->ip, &st); iunlock(f->ip); @@ -113,6 +113,8 @@ fileread(struct file *f, uint64 addr, int n) if(f->type == FD_PIPE){ r = piperead(f->pipe, addr, n); + } else if(f->type == FD_DEVICE){ + r = devsw[f->major].read(1, addr, n); } else if(f->type == FD_INODE){ ilock(f->ip); if((r = readi(f->ip, 1, addr, f->off, n)) > 0) @@ -138,6 +140,8 @@ filewrite(struct file *f, uint64 addr, int n) if(f->type == FD_PIPE){ ret = pipewrite(f->pipe, addr, n); + } else if(f->type == FD_DEVICE){ + ret = devsw[f->major].write(1, addr, n); } else if(f->type == FD_INODE){ // write a few blocks at a time to avoid exceeding // the maximum log transaction size, including diff --git a/kernel/file.h b/kernel/file.h index f28018f..5cf15a2 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -1,11 +1,12 @@ struct file { - enum { FD_NONE, FD_PIPE, FD_INODE } type; + enum { FD_NONE, FD_PIPE, FD_INODE, FD_DEVICE } type; int ref; // reference count char readable; char writable; - struct pipe *pipe; - struct inode *ip; - uint off; + struct pipe *pipe; // FD_PIPE + struct inode *ip; // FD_INODE and FD_DEVICE + uint off; // FD_INODE + short major; // FD_DEVICE }; @@ -25,11 +26,10 @@ struct inode { uint addrs[NDIRECT+1]; }; -// table mapping major device number to -// device functions +// map major device number to device functions. struct devsw { - int (*read)(struct inode*, int, uint64, int); - int (*write)(struct inode*, int, uint64, int); + int (*read)(int, uint64, int); + int (*write)(int, uint64, int); }; extern struct devsw devsw[]; diff --git a/kernel/fs.c b/kernel/fs.c index ebe377a..ebd8f7a 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -461,12 +461,6 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) uint tot, m; struct buf *bp; - if(ip->type == T_DEV){ - if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read) - return -1; - return devsw[ip->major].read(ip, user_dst, dst, n); - } - if(off > ip->size || off + n < off) return -1; if(off + n > ip->size) @@ -493,13 +487,6 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) uint tot, m; struct buf *bp; - if(ip->type == T_DEV){ - if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write){ - return -1; - } - return devsw[ip->major].write(ip, user_src, src, n); - } - if(off > ip->size || off + n < off) return -1; if(off + n > MAXFILE*BSIZE) diff --git a/kernel/fs.h b/kernel/fs.h index bc0805f..139dcc9 100644 --- a/kernel/fs.h +++ b/kernel/fs.h @@ -31,8 +31,8 @@ struct superblock { // On-disk inode structure struct dinode { short type; // File type - short major; // Major device number (T_DEV only) - short minor; // Minor device number (T_DEV only) + short major; // Major device number (T_DEVICE only) + short minor; // Minor device number (T_DEVICE only) short nlink; // Number of links to inode in file system uint size; // Size of file (bytes) uint addrs[NDIRECT+1]; // Data block addresses diff --git a/kernel/stat.h b/kernel/stat.h index 8a80933..a498321 100644 --- a/kernel/stat.h +++ b/kernel/stat.h @@ -1,6 +1,6 @@ -#define T_DIR 1 // Directory -#define T_FILE 2 // File -#define T_DEV 3 // Device +#define T_DIR 1 // Directory +#define T_FILE 2 // File +#define T_DEVICE 3 // Device struct stat { short type; // Type of file diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 83bb1ed..7788de3 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -253,7 +253,7 @@ create(char *path, short type, short major, short minor) if((ip = dirlookup(dp, name, &off)) != 0){ iunlockput(dp); ilock(ip); - if(type == T_FILE && ip->type == T_FILE) + if(type == T_FILE && (ip->type == T_FILE || ip->type == T_DEVICE)) return ip; iunlockput(ip); return 0; @@ -316,6 +316,12 @@ sys_open(void) } } + if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){ + iunlockput(ip); + end_op(); + return -1; + } + if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ if(f) fileclose(f); @@ -323,14 +329,21 @@ sys_open(void) end_op(); return -1; } + + if(ip->type == T_DEVICE){ + f->type = FD_DEVICE; + f->major = ip->major; + } else { + f->type = FD_INODE; + f->off = 0; + } + f->ip = ip; + f->readable = !(omode & O_WRONLY); + f->writable = (omode & O_WRONLY) || (omode & O_RDWR); + iunlock(ip); end_op(); - f->type = FD_INODE; - f->ip = ip; - f->off = 0; - f->readable = !(omode & O_WRONLY); - f->writable = (omode & O_WRONLY) || (omode & O_RDWR); return fd; } @@ -361,7 +374,7 @@ sys_mknod(void) if((argstr(0, path, MAXPATH)) < 0 || argint(1, &major) < 0 || argint(2, &minor) < 0 || - (ip = create(path, T_DEV, major, minor)) == 0){ + (ip = create(path, T_DEVICE, major, minor)) == 0){ end_op(); return -1; }