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));
}