Device I/O in MTX/UNIX

#define NDEV 10

struct devtab{                    // devtab struct
  int dev;                        // dev=(major,minor) numbers (2,0),(3,2),etc.
  ulong  start_sector;            // partition start sector
  ulong  size;                    
  struct buf *dev_list;           // I/O buffer assigned to this device
  struct buf *io_queue;           // I/O request queue on this device
} devtab[NDEV];                   // one devtab struct per device


struct devsw {                    // I/O function switch table type
  int (*dev_read)();
  int (*dev_write)();
} devsw[];

int nocall(){ }
int conread(),conwrite(),bread(),bwrite(),serread(),serwrite(),prwrite();

struct devsw devsw[] =            // Actual I/O switch table
{ //   read         write  
  // --------     --------
      nocall,    nocall,          // /dev/null
      nocall,    nocall,          // 1 kernel image
      bread,     bwrite,          // 2 FD r/w 
      bread,     bwrite,          // 3 HD r/w 
      conread,   conwrite,        // 4 Console
      serread,   serwrite,        // 5 Serial
      nocall,    prwrite          // 6 printer
};

int bread(dev, blk, buf) int dev,blk; char *buf;
{
    // read a block from dev=(major,minor) to buf[ ]
}

int bwrite(dev,blk,buf) int dev,blk; char *buf;
{
    // write buf[ ] to blk to dev=(major,minor);
}

int kread(fd, buf, nbytes) int fd; char *buf; int nbytes;
{
 int i, n, r, t, device, mode, major, dev; 
 char line[64], *cp;
 OFT *oftp;
 ulong size;
 ushort blk, *up;

 if (nbytes < 0){
    printf("bad nbytes\n");
    return(-1);
 }

 if (fd < 0 || fd >= NFD){
    printf("bad fd number %d\n", fd);
    return(-1);
 }

 oftp = running->fd[fd];
 if (oftp == 0){
    printf("bad fd number %d\n", fd);
    return(-1);
 }     

 if (oftp->mode != 0 && oftp->mode != 4){
    printf("fd %d is not for READ\n", fd);
    return(-1);
 }

 if (oftp->mode == READ_PIPE){
    return read_pipe(fd, buf, nbytes);
 }


 /****** READ special files ******/
 mode = oftp->inodeptr->INODE.i_mode;

 if ((mode & 0170000)==0020000){ // char special file
    device = oftp->inodeptr->INODE.i_block[0];
    major = (device & 0xFF00) >> 8;
    return (*devsw[major].dev_read)(device, buf, nbytes);
 }

 if ((mode & 0170000)==0060000){ // block special file
    device = oftp->inodeptr->INODE.i_block[0];
    major = (device & 0xFF00) >> 8;
    dev   = (device & 0x00FF);

    blk = oftp->offset / 1024;

    if (blk > devtab[dev].size/BLOCK_SIZE){
      printf("blk exceeds size\n");
      return -1;
    }
    oftp->offset += 1024;
    
    return (*devsw[major].dev_read)(device, blk, buf);
 }   

 /* read regular files */
 return myread(fd, buf, nbytes, 0);

}

int kwrite(fd, buf, nbytes) int fd; char *buf; int nbytes;
{
  char c, *cp;
  OFT *oftp;
  ushort blk, i, n, device, mode, major, dev;
 
  if (fd < 0 || fd >= NFD){
     printf("bad fd number\n", fd);
     return(-1);
  }
  oftp = running->fd[fd];
  if (oftp == 0){
      printf("bad fd number\n",fd);
      return(-1);
  }
  if (oftp->mode == 0){
      printf("fd = %d is NOT FOR WRITE", fd);
      return(-1);
  }

  if (oftp->mode == WRITE_PIPE){
     return write_pipe(fd, buf, nbytes);
  }

  /** write special files tty0, ttyS0, ttyS1, lp0, fd0 */
  mode = oftp->inodeptr->INODE.i_mode;

  if ((mode & 0170000)==0020000){ // char special
    device = oftp->inodeptr->INODE.i_block[0];
    major = (device & 0xFF00) >> 8;
    return (*devsw[major].dev_write)(device, buf, nbytes);
  }

  if ((mode & 0170000)==0060000){ // block special
    device = oftp->inodeptr->INODE.i_block[0];
    major = (device & 0xFF00) >> 8;
    dev   = (device & 0x00FF);

    blk = oftp->offset / 1024;
 
    if (blk > devtab[dev].size/BLOCK_SIZE){
       printf("blk exceeds size\n");
       return -1;
    }
    oftp->offset += 1024;
    
    return (*devsw[major].dev_write)(device, blk, buf);
  } 
  /* write regular files */
  return(mywrite(fd, buf, nbytes));
}