From a8305b7318e66eb33e7789072e8b91dffa0e4b93 Mon Sep 17 00:00:00 2001
From: Robert Morris <rtm@csail.mit.edu>
Date: Thu, 13 Jun 2019 10:29:27 -0400
Subject: FD_DEVICE

---
 kernel/console.c |  9 ++-------
 kernel/file.c    | 10 +++++++---
 kernel/file.h    | 16 ++++++++--------
 kernel/fs.c      | 13 -------------
 kernel/fs.h      |  4 ++--
 kernel/stat.h    |  6 +++---
 kernel/sysfile.c | 25 +++++++++++++++++++------
 7 files changed, 41 insertions(+), 42 deletions(-)

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;
   }
-  iunlock(ip);
-  end_op();
 
-  f->type = FD_INODE;
+  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->off = 0;
   f->readable = !(omode & O_WRONLY);
   f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
+
+  iunlock(ip);
+  end_op();
+
   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;
   }
-- 
cgit v1.2.3