Commit c27acf0e authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.96a (May 22, 1992 ??)

More VFS cleanups.  Minixfs code reorganized to be more logical, and
split up into a few new files.

SCSI support!!

 - Drew Eckhardt does the SCSI stuff, and does the ST01/ST02 lowlevel
   driver.

 - Ultrastor driver by David Gentzel.

 - Tommy Thorn shows up again.  He did the Danish keyboard tables, now
   he does the AHA 1542 driver.  Ten years later we ended up being
   co-workers at Transmeta ;)

First networking code appears: X11 port needs UNIX domain sockets, and
thus the "socketcall()" system call.  It's not really meant for real
networking, although the code will eventually evolve to support that.
Which explains some of the bad early decisions..  ;)

Werner Almerberger starts taking over floppy driver maintenance.  Thank
Gods!

Johan Myreen translates my assembly-level keyboard driver into C code,
and adds support for diacriticals.

OMAGIC a.out format support

Syslog support for the kernel appears.  If I remember correctly, this
was Peter MacDonald, but no mention of that in the sources.
parent 6891759b
#
# comment this line if you don't want the emulation-code
# ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the
# default of FLOPPY is used by 'build'.
#
MATH_EMULATION = -DKERNEL_MATH_EMULATION
ROOT_DEV = /dev/hdb1
#
# uncomment the correct keyboard:
#
# The value of KBDFLAGS should be or'ed together from the following
# bits, depending on which features you want enabled.
# 0x80 - Off: the Alt key will set bit 7 if pressed together with
# another key.
# On: the Alt key will NOT set the high bit; an escape
# character is prepended instead.
# The least significant bits control if the following keys are "dead".
# The key is dead by default if the bit is on.
# 0x01 - backquote (`)
# 0x02 - accent acute
# 0x04 - circumflex (^)
# 0x08 - tilde (~)
# 0x10 - dieresis (umlaut)
KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
# KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_US -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_FR -DKBDFLAGS=0
# KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_UK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_DVORAK -DKBDFLAGS=0
# KEYBOARD = -DKBD_FINNISH
KEYBOARD = -DKBD_US
# KEYBOARD = -DKBD_GR
# KEYBOARD = -DKBD_FR
# KEYBOARD = -DKBD_UK
# KEYBOARD = -DKBD_DK
#
# comment this line if you don't want the emulation-code
#
MATH_EMULATION = -DKERNEL_MATH_EMULATION
#
# uncomment this line if you are using gcc-1.40
......@@ -26,14 +52,6 @@ KEYBOARD = -DKBD_US
CFLAGS =-Wall -O6 -fomit-frame-pointer $(GCC_OPT)
#
# ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the
# default of FLOPPY is used by 'build'.
#
# ROOT_DEV = /dev/hdb1
#
# if you want the ram-disk device, define this to be the
# size in blocks.
......@@ -52,9 +70,10 @@ CC =gcc $(RAMDISK)
MAKE =make CFLAGS="$(CFLAGS)"
CPP =cpp -nostdinc -Iinclude
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o
FILESYSTEMS =fs/minix/minix.o
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \
kernel/blk_drv/scsi/scsi.a
MATH =kernel/math/math.a
LIBS =lib/lib.a
......@@ -71,7 +90,7 @@ all: Version Image
Version:
@./makever.sh
@echo \#define UTS_RELEASE \"0.95c-`cat .version`\" > include/linux/config_rel.h
@echo \#define UTS_RELEASE \"0.96a-`cat .version`\" > include/linux/config_rel.h
@echo \#define UTS_VERSION \"`date +%D`\" > include/linux/config_ver.h
touch include/linux/config.h
......@@ -86,7 +105,7 @@ disk: Image
dd bs=8192 if=Image of=/dev/PS0
tools/build: tools/build.c
$(CC) $(CFLAGS) \
$(CC) -static $(CFLAGS) \
-o tools/build tools/build.c
boot/head.o: boot/head.s
......@@ -107,6 +126,9 @@ kernel/math/math.a: dummy
kernel/blk_drv/blk_drv.a: dummy
(cd kernel/blk_drv; $(MAKE))
kernel/blk_drv/scsi/scsi.a: dummy
(cd kernel/blk_drv/scsi; $(MAKE))
kernel/chr_drv/chr_drv.a: dummy
(cd kernel/chr_drv; $(MAKE) KEYBOARD="$(KEYBOARD)")
......@@ -119,6 +141,9 @@ mm/mm.o: dummy
fs/fs.o: dummy
(cd fs; $(MAKE))
net/net.o: dummy
(cd net; $(MAKE))
fs/minix/minix.o: dummy
(cd fs/minix; $(MAKE))
......@@ -147,6 +172,7 @@ clean:
(cd fs;make clean)
(cd kernel;make clean)
(cd lib;make clean)
(cd net;make clean)
backup: clean
(cd .. ; tar cf - linux | compress - > backup.Z)
......@@ -159,15 +185,16 @@ dep:
(cd fs; make dep)
(cd kernel; make dep)
(cd mm; make dep)
(cd net;make dep)
(cd lib; make dep)
dummy:
### Dependencies:
init/main.o : init/main.c include/unistd.h include/sys/stat.h \
include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \
include/sys/utsname.h include/sys/param.h include/sys/resource.h \
include/utime.h include/linux/tty.h include/termios.h include/linux/sched.h \
include/linux/head.h include/linux/fs.h include/sys/dirent.h \
init/main.o : init/main.c include/stddef.h include/stdarg.h include/fcntl.h include/sys/types.h \
include/time.h include/asm/system.h include/asm/io.h include/linux/config.h \
include/linux/config_rel.h include/linux/config_ver.h include/linux/config.dist.h \
include/linux/sched.h include/linux/head.h include/linux/fs.h include/sys/dirent.h \
include/limits.h include/linux/mm.h include/linux/kernel.h include/signal.h \
include/asm/system.h include/asm/io.h include/stddef.h include/stdarg.h \
include/fcntl.h include/string.h
include/sys/param.h include/sys/time.h include/sys/resource.h include/linux/tty.h \
include/termios.h include/linux/unistd.h
This diff is collapsed.
......@@ -50,6 +50,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
memcpy_fromfs(p,buf,chars);
p += chars;
buf += chars;
bh->b_uptodate = 1;
bh->b_dirt = 1;
brelse(bh);
}
......
......@@ -47,18 +47,12 @@ static void sync_buffers(int dev)
struct buffer_head * bh;
bh = free_list;
for (i=0 ; i<NR_BUFFERS ; i++,bh = bh->b_next_free) {
#if 0
if (dev && (bh->b_dev != dev))
for (i = NR_BUFFERS*2 ; i-- > 0 ; bh = bh->b_next_free) {
if (bh->b_lock)
continue;
#endif
wait_on_buffer(bh);
#if 0
if (dev && (bh->b_dev != dev))
if (!bh->b_dirt)
continue;
#endif
if (bh->b_dirt)
ll_rw_block(WRITE,bh);
ll_rw_block(WRITE,bh);
}
}
......@@ -200,7 +194,8 @@ static inline void insert_into_queues(struct buffer_head * bh)
return;
bh->b_next = hash(bh->b_dev,bh->b_blocknr);
hash(bh->b_dev,bh->b_blocknr) = bh;
bh->b_next->b_prev = bh;
if (bh->b_next)
bh->b_next->b_prev = bh;
}
static struct buffer_head * find_buffer(int dev, int block)
......@@ -257,9 +252,7 @@ struct buffer_head * getblk(int dev,int block)
if (bh = get_hash_table(dev,block))
return bh;
buffers = NR_BUFFERS;
tmp = free_list;
do {
tmp = tmp->b_next_free;
for (tmp = free_list ; buffers-- > 0 ; tmp = tmp->b_next_free) {
if (tmp->b_count)
continue;
if (!bh || BADNESS(tmp)<BADNESS(bh)) {
......@@ -267,10 +260,12 @@ struct buffer_head * getblk(int dev,int block)
if (!BADNESS(tmp))
break;
}
#if 0
if (tmp->b_dirt)
ll_rw_block(WRITEA,tmp);
#endif
}
/* and repeat until we find something good */
} while (buffers--);
if (!bh) {
sleep_on(&buffer_wait);
goto repeat;
......@@ -279,7 +274,7 @@ struct buffer_head * getblk(int dev,int block)
if (bh->b_count)
goto repeat;
while (bh->b_dirt) {
sync_dev(bh->b_dev);
sync_buffers(bh->b_dev);
wait_on_buffer(bh);
if (bh->b_count)
goto repeat;
......@@ -383,7 +378,7 @@ struct buffer_head * breada(int dev,int first, ...)
tmp=getblk(dev,first);
if (tmp) {
if (!tmp->b_uptodate)
ll_rw_block(READA,bh);
ll_rw_block(READA,tmp);
tmp->b_count--;
}
}
......@@ -419,6 +414,7 @@ void buffer_init(long buffer_end)
h->b_next = NULL;
h->b_prev = NULL;
h->b_data = (char *) b;
h->b_reqnext = NULL;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
......
/*
* linux/fs/char_dev.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <sys/types.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <checkpoint.h>
#include <asm/segment.h>
#include <asm/io.h>
extern int tty_read(unsigned minor,char * buf,int count,unsigned short flags);
extern int tty_write(unsigned minor,char * buf,int count);
extern int lp_write(unsigned minor,char *buf, int count);
typedef (*crw_ptr)(int,unsigned,char *,int,off_t *,unsigned short);
static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
{
return ((rw==READ)?tty_read(minor,buf,count,flags):
tty_write(minor,buf,count));
}
static int rw_lp(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
{
return ((rw==READ)?-EINVAL:lp_write(minor,buf,count));
}
static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos, unsigned short flags)
{
if (current->tty<0)
return -EPERM;
return rw_ttyx(rw,current->tty,buf,count,pos,flags);
}
static int rw_ram(int rw,char * buf, int count, off_t *pos)
{
return -EIO;
}
static int rw_mem(int rw,char * buf, int count, off_t * pos)
{
char *p;
unsigned long pde, pte, tmp;
int i = count;
if (count <= 0)
return(0);
/*
* return EOF on nonexistant pages or pages swapped out to disk
*/
pde = (unsigned long) pg_dir + (*pos >> 20 & 0xffc);
if (((pte = *((unsigned long *) pde)) & 1) == 0)
return 0; /* page table not present */
pte &= 0xfffff000;
pte += *pos >> 10 & 0xffc;
if (((tmp = *((unsigned long *) pte)) & 1) == 0)
return 0;
if (rw == WRITE && (tmp & 2) == 0)
un_wp_page((unsigned long *) pte);
p = (char *) ((tmp & 0xfffff000) + (*pos & 0xfff));
while (1) {
if (rw == WRITE)
*p++ = get_fs_byte(buf++);
else
put_fs_byte(*p++, buf++);
if (--i == 0)
break;
if (count && ((unsigned long) p & 0xfff) == 0) {
if (((pte += 4) & 0xfff) == 0) {
if (((pde += 4) & 0xfff) == 0)
break;
if (((pte = *((unsigned long *) pde)) & 1) == 0)
break;
pte &= 0xfffff000;
}
if (((tmp = *((unsigned long *) pte)) & 1) == 0)
break;
if (rw == WRITE && (tmp & 2) == 0)
un_wp_page((unsigned long *) pte);
p = (char *) (tmp & 0xfffff000);
}
}
return(count - i);
}
static int rw_kmem(int rw,char * buf, int count, off_t * pos)
{
char *p=(char *) *pos;
if ((unsigned long) *pos > HIGH_MEMORY)
return 0;
if ((unsigned long) *pos + count > HIGH_MEMORY)
count = HIGH_MEMORY - *pos;
switch (rw) {
case READ:
while ((count -= 4) >= 0)
put_fs_long(*((unsigned long *) p)++,
((unsigned long *) buf)++);
count += 4;
while (--count >= 0)
put_fs_byte(*p++, buf++);
break;
case WRITE:
while (--count >= 0)
*p++ = get_fs_byte(buf++);
break;
default:
return -EINVAL;
}
p -= *pos;
*pos += (int) p;
return (int) p;
}
static int rw_port(int rw,char * buf, int count, off_t * pos)
{
int i=*pos;
while (count-->0 && i<65536) {
if (rw==READ)
put_fs_byte(inb(i),buf++);
else
outb(get_fs_byte(buf++),i);
i++;
}
i -= *pos;
*pos += i;
return i;
}
static int rw_memory(int rw, unsigned minor, char * buf, int count,
off_t * pos, unsigned short flags)
{
switch(minor) {
case 0:
return rw_ram(rw,buf,count,pos);
case 1:
return rw_mem(rw,buf,count,pos);
case 2:
return rw_kmem(rw,buf,count,pos);
case 3:
return (rw==READ)?0:count; /* rw_null */
case 4:
return rw_port(rw,buf,count,pos);
default:
return -EIO;
}
}
#define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
static crw_ptr crw_table[]={
NULL, /* nodev */
rw_memory, /* /dev/mem etc */
NULL, /* /dev/fd */
NULL, /* /dev/hd */
rw_ttyx, /* /dev/ttyx */
rw_tty, /* /dev/tty */
rw_lp, /* /dev/lp */
NULL}; /* unnamed pipes */
int char_read(struct inode * inode, struct file * filp, char * buf, int count)
{
unsigned int major,minor;
crw_ptr call_addr;
major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);
if (major >= NRDEVS)
return -ENODEV;
if (!(call_addr = crw_table[major]))
return -ENODEV;
return call_addr(READ,minor,buf,count,&filp->f_pos,filp->f_flags);
}
int char_write(struct inode * inode, struct file * filp, char * buf, int count)
{
unsigned int major,minor;
crw_ptr call_addr;
major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);
if (major >= NRDEVS)
return -ENODEV;
if (!(call_addr=crw_table[major]))
return -ENODEV;
return call_addr(WRITE,minor,buf,count,&filp->f_pos,filp->f_flags);
}
......@@ -19,7 +19,7 @@
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <linux/string.h>
#include <sys/stat.h>
#include <a.out.h>
......@@ -39,26 +39,57 @@ extern int sys_close(int fd);
*/
#define MAX_ARG_PAGES 32
/*
* Note that a shared library must be both readable and executable due to
* security reasons.
*
* Also note that we take the address to load from from the file itself.
*/
int sys_uselib(const char * library)
{
#define libnum (current->numlibraries)
struct inode * inode;
unsigned long base;
struct buffer_head * bh;
struct exec ex;
if (get_limit(0x17) != TASK_SIZE)
return -EINVAL;
if (library) {
if (!(inode=namei(library))) /* get library inode */
return -ENOENT;
} else
if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
return -EINVAL;
if (library)
inode = namei(library);
else
inode = NULL;
/* we should check filetypes (headers etc), but we don't */
iput(current->library);
current->library = NULL;
base = get_base(current->ldt[2]);
base += LIBRARY_OFFSET;
free_page_tables(base,LIBRARY_SIZE);
current->library = inode;
if (!inode)
return -ENOENT;
if (!S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
iput(inode);
return -EACCES;
}
if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
iput(inode);
return -EACCES;
}
ex = *(struct exec *) bh->b_data;
brelse(bh);
if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
iput(inode);
return -ENOEXEC;
}
current->libraries[libnum].library = inode;
current->libraries[libnum].start = ex.a_entry;
current->libraries[libnum].length = (ex.a_data+ex.a_text+0xfff) & 0xfffff000;
#if 0
printk("Loaded library %d at %08x, length %08x\n",
libnum,
current->libraries[libnum].start,
current->libraries[libnum].length);
#endif
libnum++;
return 0;
#undef libnum
}
/*
......@@ -198,6 +229,32 @@ static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
return data_limit;
}
static void read_omagic(struct inode *inode, int bytes)
{
struct buffer_head *bh;
int n, blkno, blk = 0;
char *dest = (char *) 0;
while (bytes > 0) {
if (!(blkno = bmap(inode, blk)))
sys_exit(-1);
if (!(bh = bread(inode->i_dev, blkno)))
sys_exit(-1);
n = (blk ? BLOCK_SIZE : BLOCK_SIZE - sizeof(struct exec));
if (bytes < n)
n = bytes;
memcpy_tofs(dest, (blk ? bh->b_data :
bh->b_data + sizeof(struct exec)), n);
brelse(bh);
++blk;
dest += n;
bytes -= n;
}
iput(inode);
current->executable = NULL;
}
/*
* 'do_execve()' executes a new program.
*
......@@ -328,13 +385,14 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
goto restart_interp;
}
brelse(bh);
if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
ex.a_trsize || ex.a_drsize ||
ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
retval = -ENOEXEC;
goto exec_error2;
}
if (N_TXTOFF(ex) != BLOCK_SIZE) {
if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
retval = -ENOEXEC;
goto exec_error2;
......@@ -348,7 +406,6 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
}
}
/* OK, This is the point of no return */
/* note that current->library stays unchanged by an exec */
for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
if (ch == '/')
i = 0;
......@@ -357,9 +414,14 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
current->comm[i++] = ch;
if (i < 8)
current->comm[i] = '\0';
if (current->executable)
iput(current->executable);
i = current->numlibraries;
while (i-- > 0) {
iput(current->libraries[i].library);
current->libraries[i].library = NULL;
}
current->numlibraries = 0;
current->executable = inode;
current->signal = 0;
for (i=0 ; i<32 ; i++) {
......@@ -387,6 +449,8 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
current->rss = (LIBRARY_OFFSET - p + PAGE_SIZE-1) / PAGE_SIZE;
current->suid = current->euid = e_uid;
current->sgid = current->egid = e_gid;
if (N_MAGIC(ex) == OMAGIC)
read_omagic(inode, ex.a_text+ex.a_data);
eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
if (current->flags & PF_PTRACED)
......
......@@ -4,15 +4,17 @@
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <asm/segment.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
extern int sys_close(int fd);
static int dupfd(unsigned int fd, unsigned int arg)
......
......@@ -4,7 +4,7 @@
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <linux/string.h>
#include <sys/stat.h>
#include <linux/sched.h>
......@@ -39,13 +39,13 @@ static inline void unlock_inode(struct inode * inode)
static void write_inode(struct inode * inode)
{
lock_inode(inode);
if (!inode->i_dirt || !inode->i_dev) {
unlock_inode(inode);
if (!inode->i_dirt)
return;
}
if (inode->i_op && inode->i_op->write_inode)
inode->i_op->write_inode(inode);
inode->i_dirt = 0;
lock_inode(inode);
if (inode->i_dev && inode->i_sb &&
inode->i_sb->s_op && inode->i_sb->s_op->write_inode)
inode->i_sb->s_op->write_inode(inode);
unlock_inode(inode);
}
......@@ -110,8 +110,12 @@ void iput(struct inode * inode)
if (!inode)
return;
wait_on_inode(inode);
if (!inode->i_count)
panic("iput: trying to free free inode");
if (!inode->i_count) {
printk("iput: trying to free free inode\n");
printk("device %04x, inode %d, mode=%07o\n",inode->i_rdev,
inode->i_ino,inode->i_mode);
return;
}
if (inode->i_pipe) {
wake_up(&inode->i_wait);
wake_up(&inode->i_wait2);
......@@ -127,18 +131,14 @@ void iput(struct inode * inode)
inode->i_count--;
return;
}
if (S_ISBLK(inode->i_mode)) {
sync_dev(inode->i_rdev);
wait_on_inode(inode);
}
repeat:
if (inode->i_count>1) {
inode->i_count--;
return;
}
if (!inode->i_nlink) {
if (inode->i_op && inode->i_op->put_inode)
inode->i_op->put_inode(inode);
if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode)
inode->i_sb->s_op->put_inode(inode);
return;
}
if (inode->i_dirt) {
......
......@@ -4,47 +4,19 @@
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <linux/string.h>
#include <errno.h>
#include <sys/stat.h>
#include <linux/sched.h>
extern int hd_ioctl(int dev, int cmd, int arg);
extern int tty_ioctl(int dev, int cmd, int arg);
extern int pipe_ioctl(struct inode *pino, int cmd, int arg);
typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
static ioctl_ptr ioctl_table[]={
NULL, /* nodev */
NULL, /* /dev/mem */
NULL, /* /dev/fd */
hd_ioctl, /* /dev/hd */
tty_ioctl, /* /dev/ttyx */
tty_ioctl, /* /dev/tty */
NULL, /* /dev/lp */
NULL}; /* named pipes */
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
int dev,mode;
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
if (filp->f_inode->i_pipe)
return (filp->f_mode&1)?pipe_ioctl(filp->f_inode,cmd,arg):-EBADF;
mode=filp->f_inode->i_mode;
if (!S_ISCHR(mode) && !S_ISBLK(mode))
return -EINVAL;
dev = filp->f_inode->i_rdev;
if (MAJOR(dev) >= NRDEVS)
return -ENODEV;
if (!ioctl_table[MAJOR(dev)])
return -ENOTTY;
return ioctl_table[MAJOR(dev)](dev,cmd,arg);
if (filp->f_op && filp->f_op->ioctl)
return filp->f_op->ioctl(filp->f_inode, filp, cmd,arg);
return -EINVAL;
}
......@@ -22,7 +22,8 @@ CPP =cpp -nostdinc -I../../include
.s.o:
$(AS) -o $*.o $<
OBJS= minix_op.o bitmap.o truncate.o namei.o inode.o file_dev.o
OBJS= bitmap.o truncate.o namei.o inode.o \
file.o dir.o symlink.o blkdev.o chrdev.o
minix.o: $(OBJS)
$(LD) -r -o minix.o $(OBJS)
......@@ -37,46 +38,52 @@ dep:
cp tmp_make Makefile
### Dependencies:
bitmap.o : bitmap.c ../../include/string.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
bitmap.o : bitmap.c ../../include/linux/string.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h
blkdev.o : blkdev.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h
file_dev.o : file_dev.c ../../include/errno.h ../../include/fcntl.h \
../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/linux/tty.h ../../include/asm/system.h \
../../include/termios.h ../../include/errno.h ../../include/fcntl.h ../../include/sys/stat.h
chrdev.o : chrdev.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
../../include/sys/stat.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/asm/segment.h
inode.o : inode.c ../../include/string.h ../../include/sys/stat.h \
../../include/sys/types.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h \
../../include/asm/system.h
minix_op.o : minix_op.c ../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h \
../../include/linux/minix_fs.h
namei.o : namei.c ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h \
../../include/asm/segment.h ../../include/string.h ../../include/fcntl.h \
../../include/errno.h ../../include/const.h ../../include/sys/stat.h
truncate.o : truncate.c ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/linux/tty.h ../../include/asm/system.h \
../../include/termios.h ../../include/errno.h ../../include/fcntl.h ../../include/sys/stat.h
dir.o : dir.c ../../include/errno.h ../../include/sys/stat.h ../../include/sys/types.h \
../../include/asm/segment.h ../../include/linux/fs.h ../../include/sys/dirent.h \
../../include/limits.h ../../include/linux/minix_fs.h
file.o : file.c ../../include/errno.h ../../include/fcntl.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/sys/stat.h ../../include/asm/segment.h \
../../include/asm/system.h ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h
inode.o : inode.c ../../include/linux/string.h ../../include/sys/stat.h ../../include/sys/types.h \
../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/asm/system.h
namei.o : namei.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/linux/tty.h \
../../include/termios.h ../../include/errno.h ../../include/fcntl.h \
../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/asm/segment.h ../../include/linux/string.h \
../../include/fcntl.h ../../include/errno.h ../../include/const.h ../../include/sys/stat.h
symlink.o : symlink.c ../../include/errno.h ../../include/sys/stat.h ../../include/sys/types.h \
../../include/asm/segment.h ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h ../../include/sys/param.h \
../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h ../../include/linux/minix_fs.h
truncate.o : truncate.c ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h ../../include/sys/dirent.h \
../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h ../../include/linux/tty.h \
../../include/asm/system.h ../../include/termios.h ../../include/errno.h ../../include/fcntl.h \
../../include/sys/stat.h
......@@ -5,7 +5,7 @@
*/
/* bitmap.c contains the code that handles the inode and block bitmaps */
#include <string.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
......@@ -179,6 +179,6 @@ struct inode * minix_new_inode(int dev)
inode->i_dirt = 1;
inode->i_ino = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &minix_inode_operations;
inode->i_op = NULL;
return inode;
}
/*
* linux/fs/chrdev.c
*
* (C) 1991 Linus Torvalds
*/
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/tty.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
/*
* Called every time a minix block special file is opened
*/
static int blkdev_open(struct inode * inode, struct file * filp)
{
int i;
check_disk_change(inode->i_rdev);
i = MAJOR(inode->i_rdev);
if (i < MAX_BLKDEV) {
filp->f_op = blkdev_fops[i];
if (filp->f_op && filp->f_op->open)
return filp->f_op->open(inode,filp);
}
return 0;
}
/*
* Dummy default file-operations: the only thing this does
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
static struct file_operations def_blk_fops = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
blkdev_open, /* open */
NULL, /* release */
};
struct inode_operations minix_blkdev_inode_operations = {
&def_blk_fops, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
minix_bmap, /* bmap */
minix_truncate /* truncate */
};
/*
* linux/fs/chrdev.c
*
* (C) 1991 Linus Torvalds
*/
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/tty.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
/*
* Called every time a minix character special file is opened
*/
static int chrdev_open(struct inode * inode, struct file * filp)
{
int i;
i = MAJOR(inode->i_rdev);
if (i < MAX_CHRDEV) {
filp->f_op = chrdev_fops[i];
if (filp->f_op && filp->f_op->open)
return filp->f_op->open(inode,filp);
}
return 0;
}
/*
* Dummy default file-operations: the only thing this does
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
static struct file_operations def_chr_fops = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* select */
NULL, /* ioctl */
chrdev_open, /* open */
NULL, /* release */
};
struct inode_operations minix_chrdev_inode_operations = {
&def_chr_fops, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
minix_bmap, /* bmap */
minix_truncate /* truncate */
};
/*
* linux/fs/minix/dir.c
*
* minix directory hadnling functions
*/
#include <errno.h>
#include <sys/stat.h>
#include <asm/segment.h>
#include <linux/fs.h>
#include <linux/minix_fs.h>
static int minix_readdir(struct inode *, struct file *, struct dirent *, int);
static struct file_operations minix_dir_operations = {
NULL, /* lseek - default */
minix_file_read, /* read */
NULL, /* write - bad */
minix_readdir, /* readdir */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open code */
NULL /* no special release code */
};
/*
* directories can handle most operations...
*/
struct inode_operations minix_dir_inode_operations = {
&minix_dir_operations, /* default directory file-ops */
minix_create, /* create */
minix_lookup, /* lookup */
minix_link, /* link */
minix_unlink, /* unlink */
minix_symlink, /* symlink */
minix_mkdir, /* mkdir */
minix_rmdir, /* rmdir */
minix_mknod, /* mknod */
minix_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
minix_bmap, /* bmap */
minix_truncate /* truncate */
};
static int minix_readdir(struct inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
unsigned int block,offset,i;
char c;
struct buffer_head * bh;
struct minix_dir_entry * de;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
if (filp->f_pos & (sizeof (struct minix_dir_entry) - 1))
return -EBADF;
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
if (!block || !(bh = bread(inode->i_dev,block))) {
filp->f_pos += 1024-offset;
continue;
}
de = (struct minix_dir_entry *) (offset + bh->b_data);
while (offset < 1024 && filp->f_pos < inode->i_size) {
offset += sizeof (struct minix_dir_entry);
filp->f_pos += sizeof (struct minix_dir_entry);
if (de->inode) {
for (i = 0; i < MINIX_NAME_LEN; i++)
if (c = de->name[i])
put_fs_byte(c,i+dirent->d_name);
else
break;
if (i) {
put_fs_long(de->inode,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
return i;
}
}
de++;
}
brelse(bh);
}
return 0;
}
/*
* linux/fs/file_dev.c
* linux/fs/minix/file.c
*
* (C) 1991 Linus Torvalds
* minix regular file handling primitives
*/
#include <errno.h>
#include <fcntl.h>
#include <sys/dirent.h>
#include <sys/stat.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#define NBUF 16
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent)
#include <linux/fs.h>
#include <linux/minix_fs.h>
int minix_file_read(struct inode *, struct file *, char *, int);
static int minix_file_write(struct inode *, struct file *, char *, int);
/*
* We have mostly NULL's here: the current defaults are ok for
* the minix filesystem.
*/
static struct file_operations minix_file_operations = {
NULL, /* lseek - default */
minix_file_read, /* read */
minix_file_write, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* no special open is needed */
NULL /* release */
};
struct inode_operations minix_file_inode_operations = {
&minix_file_operations, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
minix_bmap, /* bmap */
minix_truncate /* truncate */
};
static inline void wait_on_buffer(struct buffer_head * bh)
{
unsigned int block,offset,i;
char c;
struct buffer_head * bh;
struct minix_dir_entry * de;
if (!S_ISDIR(inode->i_mode))
return -EBADF;
if (filp->f_pos & 15)
return -EBADF;
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
if (!block || !(bh = bread(inode->i_dev,block))) {
filp->f_pos += 1024-offset;
continue;
}
de = (struct minix_dir_entry *) (offset + bh->b_data);
while (offset < 1024 && filp->f_pos < inode->i_size) {
offset += 16;
filp->f_pos += 16;
if (de->inode) {
for (i = 0; i < 14; i++)
if (c = de->name[i])
put_fs_byte(c,i+dirent->d_name);
else
break;
if (i) {
put_fs_long(de->inode,&dirent->d_ino);
put_fs_byte(0,i+dirent->d_name);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
return i;
}
}
de++;
}
brelse(bh);
}
return 0;
cli();
while (bh->b_lock)
sleep_on(&bh->b_wait);
sti();
}
/*
* minix_file_read() is also needed by the directory read-routine,
* so it's not static. NOTE! reading directories directly is a bad idea,
* but has to be supported for now for compatability reasons with older
* versions.
*/
int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{
int read,left,chars,nr;
struct buffer_head * bh;
int block, blocks, offset;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * buflist[NBUF];
if (!inode) {
printk("minix_file_read: inode = NULL\n");
return -EINVAL;
}
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
printk("minix_file_read: mode = %07o\n",inode->i_mode);
return -EINVAL;
}
if (filp->f_pos > inode->i_size)
left = 0;
else
left = inode->i_size - filp->f_pos;
if (left > count)
left = count;
if (left <= 0)
return 0;
read = 0;
while (left > 0) {
if (nr = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS)) {
if (!(bh=bread(inode->i_dev,nr)))
return read?read:-EIO;
} else
bh = NULL;
nr = filp->f_pos & (BLOCK_SIZE-1);
chars = MIN( BLOCK_SIZE-nr , left );
block = filp->f_pos >> BLOCK_SIZE_BITS;
offset = filp->f_pos & (BLOCK_SIZE-1);
blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE;
bhb = bhe = buflist;
do {
if (blocks) {
--blocks;
if (nr = minix_bmap(inode,block++)) {
*bhb = getblk(inode->i_dev,nr);
if (!(*bhb)->b_uptodate)
ll_rw_block(READ,*bhb);
} else
*bhb = NULL;
if (++bhb == &buflist[NBUF])
bhb = buflist;
if (bhb != bhe)
continue;
}
if (*bhe) {
wait_on_buffer(*bhe);
if (!(*bhe)->b_uptodate) {
do {
brelse(*bhe);
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (bhe != bhb);
break;
}
}
if (left < BLOCK_SIZE - offset)
chars = left;
else
chars = BLOCK_SIZE - offset;
filp->f_pos += chars;
left -= chars;
read += chars;
if (bh) {
memcpy_tofs(buf,nr+bh->b_data,chars);
if (*bhe) {
memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
brelse(*bhe);
buf += chars;
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
offset = 0;
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (left > 0);
if (!read)
return -EIO;
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
return read;
}
int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
static int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
{
off_t pos;
int written,block,c;
struct buffer_head * bh;
char * p;
if (!inode) {
printk("minix_file_write: inode = NULL\n");
return -EINVAL;
}
if (!S_ISREG(inode->i_mode)) {
printk("minix_file_write: mode = %07o\n",inode->i_mode);
return -EINVAL;
}
/*
* ok, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway.
......@@ -118,16 +186,19 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
written = -ENOSPC;
break;
}
if (!(bh=bread(inode->i_dev,block))) {
c = BLOCK_SIZE - (pos % BLOCK_SIZE);
if (c > count-written)
c = count-written;
if (c == BLOCK_SIZE)
bh = getblk(inode->i_dev, block);
else
bh = bread(inode->i_dev,block);
if (!bh) {
if (!written)
written = -EIO;
break;
}
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
c = BLOCK_SIZE-c;
if (c > count-written)
c = count-written;
p = (pos % BLOCK_SIZE) + bh->b_data;
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
......@@ -136,6 +207,7 @@ int minix_file_write(struct inode * inode, struct file * filp, char * buf, int c
written += c;
memcpy_fromfs(p,buf,c);
buf += c;
bh->b_uptodate = 1;
bh->b_dirt = 1;
brelse(bh);
}
......
......@@ -4,7 +4,7 @@
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <linux/string.h>
#include <sys/stat.h>
#include <linux/sched.h>
......@@ -15,6 +15,13 @@
int sync_dev(int dev);
void minix_put_inode(struct inode *inode)
{
inode->i_size = 0;
minix_truncate(inode);
minix_free_inode(inode);
}
void minix_put_super(struct super_block *sb)
{
int i;
......@@ -31,6 +38,8 @@ void minix_put_super(struct super_block *sb)
static struct super_operations minix_sops = {
minix_read_inode,
minix_write_inode,
minix_put_inode,
minix_put_super
};
......@@ -199,7 +208,17 @@ void minix_read_inode(struct inode * inode)
else for (block = 0; block < 9; block++)
inode->i_data[block] = raw_inode->i_zone[block];
brelse(bh);
inode->i_op = &minix_inode_operations;
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &minix_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
inode->i_op = &minix_chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
inode->i_op = &minix_blkdev_inode_operations;
}
void minix_write_inode(struct inode * inode)
......
/*
* linux/fs/minix/minix_op.c
*
* structures for the minix super_block/inode/file-operations
*/
#include <linux/fs.h>
#include <linux/minix_fs.h>
void minix_put_inode(struct inode *inode)
{
minix_truncate(inode);
minix_free_inode(inode);
}
/*
* These are the low-level inode operations for minix filesystem inodes.
*/
struct inode_operations minix_inode_operations = {
minix_create,
minix_lookup,
minix_link,
minix_unlink,
minix_symlink,
minix_mkdir,
minix_rmdir,
minix_mknod,
minix_rename,
minix_readlink,
minix_open,
minix_release,
minix_follow_link,
minix_bmap,
minix_truncate,
minix_write_inode,
minix_put_inode
};
/*
* We have mostly NULL's here: the current defaults are ok for
* the minix filesystem.
*/
struct file_operations minix_file_operations = {
NULL, /* lseek */
NULL, /* read */
NULL, /* write */
minix_readdir
};
......@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <asm/segment.h>
#include <string.h>
#include <linux/string.h>
#include <fcntl.h>
#include <errno.h>
#include <const.h>
......@@ -103,40 +103,6 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
return NULL;
}
struct inode * minix_follow_link(struct inode * dir, struct inode * inode)
{
unsigned short fs;
struct buffer_head * bh;
if (!dir) {
dir = current->root;
dir->i_count++;
}
if (!inode) {
iput(dir);
return NULL;
}
if (!S_ISLNK(inode->i_mode)) {
iput(dir);
return inode;
}
__asm__("mov %%fs,%0":"=r" (fs));
if ((current->link_count > 5) || !inode->i_data[0] ||
!(bh = bread(inode->i_dev, inode->i_data[0]))) {
iput(dir);
iput(inode);
return NULL;
}
iput(inode);
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
current->link_count++;
inode = _namei(bh->b_data,dir,1);
current->link_count--;
__asm__("mov %0,%%fs"::"r" (fs));
brelse(bh);
return inode;
}
int minix_lookup(struct inode * dir,const char * name, int len,
struct inode ** result)
{
......@@ -249,11 +215,13 @@ int minix_create(struct inode * dir,const char * name, int len, int mode,
iput(dir);
return -ENOSPC;
}
inode->i_op = &minix_file_inode_operations;
inode->i_mode = mode;
inode->i_dirt = 1;
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
iput(dir);
return -ENOSPC;
......@@ -287,6 +255,17 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
}
inode->i_uid = current->euid;
inode->i_mode = mode;
inode->i_op = NULL;
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &minix_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &minix_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode))
inode->i_op = &minix_chrdev_inode_operations;
else if (S_ISBLK(inode->i_mode))
inode->i_op = &minix_blkdev_inode_operations;
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = rdev;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
......@@ -294,6 +273,7 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
iput(dir);
return -ENOSPC;
......@@ -323,12 +303,13 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
iput(dir);
return -ENOSPC;
}
inode->i_size = 32;
inode->i_dirt = 1;
inode->i_op = &minix_dir_inode_operations;
inode->i_size = 2 * sizeof (struct minix_dir_entry);
inode->i_mtime = inode->i_atime = CURRENT_TIME;
if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -ENOSPC;
}
......@@ -336,8 +317,9 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -ERROR;
return -EIO;
}
de = (struct minix_dir_entry *) dir_block->b_data;
de->inode=inode->i_ino;
......@@ -517,10 +499,11 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
return -ENOSPC;
}
inode->i_mode = S_IFLNK | 0777;
inode->i_dirt = 1;
inode->i_op = &minix_symlink_inode_operations;
if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -ENOSPC;
}
......@@ -528,8 +511,9 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
return -ERROR;
return -EIO;
}
i = 0;
while (i < 1023 && (c=get_fs_byte(symname++)))
......@@ -542,6 +526,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
bh = minix_find_entry(dir,name,len,&de);
if (bh) {
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
brelse(bh);
iput(dir);
......@@ -550,6 +535,7 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
bh = minix_add_entry(dir,name,len,&de);
if (!bh) {
inode->i_nlink--;
inode->i_dirt = 1;
iput(inode);
iput(dir);
return -ENOSPC;
......@@ -667,6 +653,10 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol
old_inode = iget(old_dir->i_dev, old_de->inode);
if (!old_inode)
goto end_rename;
if ((old_dir->i_mode & S_ISVTX) &&
current->euid != old_inode->i_uid &&
current->euid != old_dir->i_uid && !suser())
goto end_rename;
new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
if (new_bh) {
new_inode = iget(new_dir->i_dev, new_de->inode);
......@@ -712,8 +702,10 @@ static int do_minix_rename(struct inode * old_dir, const char * old_name, int ol
/* ok, that's it */
old_de->inode = 0;
new_de->inode = old_inode->i_ino;
if (new_inode)
if (new_inode) {
new_inode->i_nlink--;
new_inode->i_dirt = 1;
}
old_bh->b_dirt = 1;
new_bh->b_dirt = 1;
if (dir_bh) {
......@@ -761,31 +753,3 @@ int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
wake_up(&wait);
return result;
}
int minix_readlink(struct inode * inode, char * buffer, int buflen)
{
struct buffer_head * bh;
int i;
char c;
if (!S_ISLNK(inode->i_mode)) {
iput(inode);
return -EINVAL;
}
if (buflen > 1023)
buflen = 1023;
if (inode->i_data[0])
bh = bread(inode->i_dev, inode->i_data[0]);
else
bh = NULL;
iput(inode);
if (!bh)
return 0;
i = 0;
while (i<buflen && (c = bh->b_data[i])) {
i++;
put_fs_byte(c,buffer++);
}
brelse(bh);
return i;
}
/*
* linux/fs/minix/symlink.c
*
* minix symlink handling code
*/
#include <errno.h>
#include <sys/stat.h>
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/minix_fs.h>
static int minix_readlink(struct inode *, char *, int);
static struct inode * minix_follow_link(struct inode *, struct inode *);
/*
* symlinks can't do much...
*/
struct inode_operations minix_symlink_inode_operations = {
NULL, /* no file-operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
minix_readlink, /* readlink */
minix_follow_link, /* follow_link */
NULL, /* bmap */
NULL /* truncate */
};
static struct inode * minix_follow_link(struct inode * dir, struct inode * inode)
{
unsigned short fs;
struct buffer_head * bh;
if (!dir) {
dir = current->root;
dir->i_count++;
}
if (!inode) {
iput(dir);
return NULL;
}
if (!S_ISLNK(inode->i_mode)) {
iput(dir);
return inode;
}
__asm__("mov %%fs,%0":"=r" (fs));
if ((current->link_count > 5) || !inode->i_data[0] ||
!(bh = bread(inode->i_dev, inode->i_data[0]))) {
iput(dir);
iput(inode);
return NULL;
}
iput(inode);
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
current->link_count++;
inode = _namei(bh->b_data,dir,1);
current->link_count--;
__asm__("mov %0,%%fs"::"r" (fs));
brelse(bh);
return inode;
}
static int minix_readlink(struct inode * inode, char * buffer, int buflen)
{
struct buffer_head * bh;
int i;
char c;
if (!S_ISLNK(inode->i_mode)) {
iput(inode);
return -EINVAL;
}
if (buflen > 1023)
buflen = 1023;
if (inode->i_data[0])
bh = bread(inode->i_dev, inode->i_data[0]);
else
bh = NULL;
iput(inode);
if (!bh)
return 0;
i = 0;
while (i<buflen && (c = bh->b_data[i])) {
i++;
put_fs_byte(c,buffer++);
}
brelse(bh);
return i;
}
......@@ -12,93 +12,132 @@
#include <fcntl.h>
#include <sys/stat.h>
static int minix_free_ind(int dev,int block)
/*
* Truncate has the most races in the whole filesystem: coding it is
* a pain in the a**. Especially as I don't do any locking...
*
* The code may look a bit weird, but that's just because I've tried to
* handle things like file-size changes in a somewhat graceful manner.
* Anyway, truncating a file at the same time somebody else writes to it
* is likely to result in pretty weird behaviour...
*
* The new code handles normal truncates (size = 0) as well as the more
* general case (size = XXX). I hope.
*/
static int trunc_direct(struct inode * inode)
{
struct buffer_head * bh;
unsigned short * p;
int i;
int block_busy;
int result = 0;
#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
if (!block)
return 1;
block_busy = 0;
if (bh=bread(dev,block)) {
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
if (minix_free_block(dev,*p)) {
*p = 0;
bh->b_dirt = 1;
} else
block_busy = 1;
brelse(bh);
repeat:
for (i = DIRECT_BLOCK ; i < 7 ; i++) {
if (i < DIRECT_BLOCK)
goto repeat;
if (!inode->i_data[i])
continue;
result = 1;
if (minix_free_block(inode->i_dev,inode->i_data[i]))
inode->i_data[i] = 0;
}
if (block_busy)
return 0;
else
return minix_free_block(dev,block);
return result;
}
static int minix_free_dind(int dev,int block)
static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
{
struct buffer_head * bh;
unsigned short * p;
int i;
int block_busy;
struct buffer_head * bh = NULL;
unsigned short * ind;
int result = 0;
#define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
if (!block)
return 1;
block_busy = 0;
if (bh=bread(dev,block)) {
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
if (minix_free_ind(dev,*p)) {
*p = 0;
bh->b_dirt = 1;
} else
block_busy = 1;
brelse(bh);
}
if (block_busy)
if (*p)
bh = bread(inode->i_dev,*p);
if (!bh)
return 0;
else
return minix_free_block(dev,block);
repeat:
for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
if (i < 0)
i = 0;
if (i < INDIRECT_BLOCK)
goto repeat;
ind = i+(unsigned short *) bh->b_data;
if (!*ind)
continue;
result = 1;
if (minix_free_block(inode->i_dev,*ind))
*ind = 0;
}
ind = (unsigned short *) bh->b_data;
for (i = 0; i < 512; i++)
if (*(ind++))
break;
brelse(bh);
if (i >= 512) {
result = 1;
if (minix_free_block(inode->i_dev,*p))
*p = 0;
}
return result;
}
static int trunc_dindirect(struct inode * inode)
{
int i;
struct buffer_head * bh = NULL;
unsigned short * dind;
int result = 0;
#define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
if (inode->i_data[8])
bh = bread(inode->i_dev,inode->i_data[8]);
if (!bh)
return 0;
repeat:
for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
if (i < 0)
i = 0;
if (i < DINDIRECT_BLOCK)
goto repeat;
dind = i+(unsigned short *) bh->b_data;
if (!*dind)
continue;
result |= trunc_indirect(inode,7+512+(i<<9),dind);
}
dind = (unsigned short *) bh->b_data;
for (i = 0; i < 512; i++)
if (*(dind++))
break;
brelse(bh);
if (i >= 512) {
result = 1;
if (minix_free_block(inode->i_dev,inode->i_data[8]))
inode->i_data[8] = 0;
}
return result;
}
void minix_truncate(struct inode * inode)
{
int i;
int block_busy;
int flag;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
repeat:
block_busy = 0;
for (i=0;i<7;i++)
if (inode->i_data[i]) {
if (minix_free_block(inode->i_dev,inode->i_data[i]))
inode->i_data[i]=0;
else
block_busy = 1;
}
if (minix_free_ind(inode->i_dev,inode->i_data[7]))
inode->i_data[7] = 0;
else
block_busy = 1;
if (minix_free_dind(inode->i_dev,inode->i_data[8]))
inode->i_data[8] = 0;
else
block_busy = 1;
inode->i_dirt = 1;
if (block_busy) {
if (inode->i_data[7] & 0xffff0000)
printk("BAD! minix inode has 16 high bits set\n");
while (1) {
flag = trunc_direct(inode);
flag |= trunc_indirect(inode,7,(unsigned short *)&inode->i_data[7]);
flag |= trunc_dindirect(inode);
if (!flag)
break;
current->counter = 0;
schedule();
goto repeat;
}
inode->i_size = 0;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
}
/*
......@@ -110,47 +149,3 @@ void minix_release(struct inode * inode, struct file * filp)
{
printk("minix_release not implemented\n");
}
static int check_char_dev(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
int min, dev;
dev = inode->i_rdev;
if (MAJOR(dev) == 4 || MAJOR(dev) == 5) {
if (MAJOR(dev) == 5)
min = current->tty;
else
min = MINOR(dev);
if (min < 0)
return -1;
if ((IS_A_PTY_MASTER(min)) && (inode->i_count>1))
return -1;
tty = TTY_TABLE(min);
if (!(filp->f_flags & O_NOCTTY) &&
current->leader &&
current->tty<0 &&
tty->session==0) {
current->tty = min;
tty->session= current->session;
tty->pgrp = current->pgrp;
}
if (IS_A_SERIAL(min))
serial_open(min-64);
}
return 0;
}
/*
* Called every time a minix-file is opened
*/
int minix_open(struct inode * inode, struct file * filp)
{
if (S_ISCHR(inode->i_mode)) {
if (check_char_dev(inode,filp))
return -EAGAIN;
} else if (S_ISBLK(inode->i_mode))
check_disk_change(inode->i_rdev);
filp->f_op = &minix_file_operations;
return 0;
}
......@@ -12,7 +12,7 @@
#include <linux/kernel.h>
#include <asm/segment.h>
#include <string.h>
#include <linux/string.h>
#include <fcntl.h>
#include <errno.h>
#include <const.h>
......@@ -167,10 +167,6 @@ struct inode * _namei(const char * pathname, struct inode * base,
inode = follow_link(base,inode);
else
iput(base);
if (inode) {
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode;
}
......@@ -248,8 +244,10 @@ int open_namei(const char * pathname, int flag, int mode,
}
inode->i_atime = CURRENT_TIME;
if (flag & O_TRUNC)
if (inode->i_op && inode->i_op->truncate)
if (inode->i_op && inode->i_op->truncate) {
inode->i_size = 0;
inode->i_op->truncate(inode);
}
*res_inode = inode;
return 0;
}
......
......@@ -4,23 +4,83 @@
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utime.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
struct file_operations * chrdev_fops[MAX_CHRDEV] = {
NULL,
};
struct file_operations * blkdev_fops[MAX_BLKDEV] = {
NULL,
};
int sys_ustat(int dev, struct ustat * ubuf)
{
return -ENOSYS;
}
int sys_statfs(const char * path, struct statfs * buf)
{
printk("statfs not implemented\n");
return -ENOSYS;
}
int sys_fstatfs(unsigned int fd, struct statfs * buf)
{
printk("fstatfs not implemented\n");
return -ENOSYS;
}
int sys_truncate(const char * path, unsigned int length)
{
struct inode * inode;
if (!(inode = namei(path)))
return -ENOENT;
if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
iput(inode);
return -EACCES;
}
inode->i_size = length;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
inode->i_atime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1;
iput(inode);
return 0;
}
int sys_ftruncate(unsigned int fd, unsigned int length)
{
struct inode * inode;
struct file * file;
if (fd >= NR_OPEN || !(file = current->filp[fd]))
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
if (S_ISDIR(inode->i_mode) || !(file->f_flags & 2))
return -EACCES;
inode->i_size = length;
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
inode->i_atime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1;
return 0;
}
int sys_utime(char * filename, struct utimbuf * times)
{
struct inode * inode;
......@@ -32,7 +92,7 @@ int sys_utime(char * filename, struct utimbuf * times)
if (current->euid != inode->i_uid &&
!permission(inode,MAY_WRITE)) {
iput(inode);
return -EPERM;
return -EACCES;
}
actime = get_fs_long((unsigned long *) &times->actime);
modtime = get_fs_long((unsigned long *) &times->modtime);
......@@ -87,6 +147,10 @@ int sys_chdir(const char * filename)
iput(inode);
return -ENOTDIR;
}
if (!permission(inode,MAY_EXEC)) {
iput(inode);
return -EACCES;
}
iput(current->pwd);
current->pwd = inode;
return (0);
......@@ -102,20 +166,40 @@ int sys_chroot(const char * filename)
iput(inode);
return -ENOTDIR;
}
if (!suser()) {
iput(inode);
return -EPERM;
}
iput(current->root);
current->root = inode;
return (0);
}
int sys_chmod(const char * filename,int mode)
int sys_fchmod(unsigned int fd, mode_t mode)
{
struct inode * inode;
struct file * file;
if (!(inode=namei(filename)))
if (fd >= NR_OPEN || !(file = current->filp[fd]))
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
if ((current->euid != inode->i_uid) && !suser())
return -EPERM;
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
inode->i_dirt = 1;
return 0;
}
int sys_chmod(const char * filename, mode_t mode)
{
struct inode * inode;
if (!(inode = namei(filename)))
return -ENOENT;
if ((current->euid != inode->i_uid) && !suser()) {
iput(inode);
return -EACCES;
return -EPERM;
}
inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
inode->i_dirt = 1;
......@@ -123,21 +207,43 @@ int sys_chmod(const char * filename,int mode)
return 0;
}
int sys_chown(const char * filename,int uid,int gid)
int sys_fchown(unsigned int fd, uid_t user, gid_t group)
{
struct inode * inode;
struct file * file;
if (!(inode=namei(filename)))
if (fd >= NR_OPEN || !(file = current->filp[fd]))
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
if (!suser()) {
if ((current->euid == inode->i_uid && user == inode->i_uid &&
(in_group_p(group) || group == inode->i_gid)) ||
suser()) {
inode->i_uid = user;
inode->i_gid = group;
inode->i_dirt=1;
return 0;
}
return -EPERM;
}
int sys_chown(const char * filename, uid_t user, gid_t group)
{
struct inode * inode;
if (!(inode = lnamei(filename)))
return -ENOENT;
if ((current->euid == inode->i_uid && user == inode->i_uid &&
(in_group_p(group) || group == inode->i_gid)) ||
suser()) {
inode->i_uid = user;
inode->i_gid = group;
inode->i_dirt=1;
iput(inode);
return -EACCES;
return 0;
}
inode->i_uid=uid;
inode->i_gid=gid;
inode->i_dirt=1;
iput(inode);
return 0;
return -EPERM;
}
int sys_open(const char * filename,int flag,int mode)
......@@ -157,20 +263,23 @@ int sys_open(const char * filename,int flag,int mode)
if (!f->f_count) break;
if (i>=NR_FILE)
return -EINVAL;
(current->filp[fd]=f)->f_count++;
if ((i=open_namei(filename,flag,mode,&inode))<0) {
(current->filp[fd] = f)->f_count++;
if ((i = open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL;
f->f_count=0;
return i;
}
f->f_op = NULL;
f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
f->f_flags = flag;
f->f_count = 1;
f->f_inode = inode;
f->f_pos = 0;
if (inode->i_op && inode->i_op->open)
if (i = inode->i_op->open(inode,f)) {
f->f_reada = 0;
f->f_op = NULL;
if (inode->i_op)
f->f_op = inode->i_op->default_file_ops;
if (f->f_op && f->f_op->open)
if (i = f->f_op->open(inode,f)) {
iput(inode);
f->f_count=0;
current->filp[fd]=NULL;
......@@ -194,10 +303,17 @@ int sys_close(unsigned int fd)
if (!(filp = current->filp[fd]))
return -EINVAL;
current->filp[fd] = NULL;
if (filp->f_count == 0)
panic("Close: file count is 0");
if (--filp->f_count)
return (0);
if (filp->f_count == 0) {
printk("Close: file count is 0\n");
return 0;
}
if (filp->f_count > 1) {
filp->f_count--;
return 0;
}
if (filp->f_op && filp->f_op->release)
filp->f_op->release(filp->f_inode,filp);
iput(filp->f_inode);
return (0);
filp->f_count--;
return 0;
}
......@@ -9,11 +9,12 @@
#include <termios.h>
#include <fcntl.h>
#include <linux/sched.h>
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/kernel.h>
int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
{
int chars, size, read = 0;
......@@ -44,7 +45,7 @@ int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
return read?read:-EAGAIN;
}
int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
{
int chars, size, written = 0;
......@@ -76,6 +77,68 @@ int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
return written;
}
static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
{
return -ESPIPE;
}
static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
{
return -ENOTDIR;
}
static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count)
{
return -EBADF;
}
static int pipe_ioctl(struct inode *pino, struct file * filp,
unsigned int cmd, unsigned int arg)
{
switch (cmd) {
case FIONREAD:
verify_area((void *) arg,4);
put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
return 0;
default:
return -EINVAL;
}
}
/*
* Ok, these two routines should keep track of readers/writers,
* but it's currently done with the inode->i_count checking.
*/
static void pipe_read_release(struct inode * inode, struct file * filp)
{
}
static void pipe_write_release(struct inode * inode, struct file * filp)
{
}
static struct file_operations read_pipe_fops = {
pipe_lseek,
pipe_read,
bad_pipe_rw,
pipe_readdir,
NULL, /* pipe_select */
pipe_ioctl,
NULL, /* no special open code */
pipe_read_release
};
static struct file_operations write_pipe_fops = {
pipe_lseek,
bad_pipe_rw,
pipe_write,
pipe_readdir,
NULL, /* pipe_select */
pipe_ioctl,
NULL, /* no special open code */
pipe_write_release
};
int sys_pipe(unsigned long * fildes)
{
struct inode * inode;
......@@ -111,21 +174,11 @@ int sys_pipe(unsigned long * fildes)
}
f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0;
f[0]->f_op = &read_pipe_fops;
f[0]->f_mode = 1; /* read */
f[1]->f_op = &write_pipe_fops;
f[1]->f_mode = 2; /* write */
put_fs_long(fd[0],0+fildes);
put_fs_long(fd[1],1+fildes);
return 0;
}
int pipe_ioctl(struct inode *pino, int cmd, int arg)
{
switch (cmd) {
case FIONREAD:
verify_area((void *) arg,4);
put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
return 0;
default:
return -EINVAL;
}
}
......@@ -28,43 +28,41 @@ int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
return -EBADF;
if (file->f_op && file->f_op->readdir) {
verify_area(dirent, sizeof (*dirent));
return file->f_op->readdir(inode,file,dirent);
return file->f_op->readdir(inode,file,dirent,count);
}
return -EBADF;
return -ENOTDIR;
}
int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
{
struct file * file;
int tmp, mem_dev;
int tmp;
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode))
return -EBADF;
if (origin > 2)
return -EINVAL;
if (file->f_inode->i_pipe)
return -ESPIPE;
if (file->f_op && file->f_op->lseek)
return file->f_op->lseek(file->f_inode,file,offset,origin);
mem_dev = S_ISCHR(file->f_inode->i_mode);
/* this is the default handler if no lseek handler is present */
switch (origin) {
case 0:
if (offset<0 && !mem_dev) return -EINVAL;
file->f_pos=offset;
tmp = offset;
break;
case 1:
if (file->f_pos+offset<0 && !mem_dev) return -EINVAL;
file->f_pos += offset;
tmp = file->f_pos + offset;
break;
case 2:
if ((tmp=file->f_inode->i_size+offset)<0 && !mem_dev)
if (!file->f_inode)
return -EINVAL;
file->f_pos = tmp;
tmp = file->f_inode->i_size + offset;
break;
}
if (mem_dev && file->f_pos < 0)
return 0;
if (tmp < 0)
return -EINVAL;
file->f_pos = tmp;
file->f_reada = 0;
return file->f_pos;
}
......@@ -82,15 +80,6 @@ int sys_read(unsigned int fd,char * buf,unsigned int count)
verify_area(buf,count);
if (file->f_op && file->f_op->read)
return file->f_op->read(inode,file,buf,count);
/* these are the default read-functions */
if (inode->i_pipe)
return pipe_read(inode,file,buf,count);
if (S_ISCHR(inode->i_mode))
return char_read(inode,file,buf,count);
if (S_ISBLK(inode->i_mode))
return block_read(inode,file,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode))
return minix_file_read(inode,file,buf,count);
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
......@@ -108,15 +97,6 @@ int sys_write(unsigned int fd,char * buf,unsigned int count)
return 0;
if (file->f_op && file->f_op->write)
return file->f_op->write(inode,file,buf,count);
/* these are the default read-functions */
if (inode->i_pipe)
return pipe_write(inode,file,buf,count);
if (S_ISCHR(inode->i_mode))
return char_write(inode,file,buf,count);
if (S_ISBLK(inode->i_mode))
return block_write(inode,file,buf,count);
if (S_ISREG(inode->i_mode))
return minix_file_write(inode,file,buf,count);
printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
......@@ -9,16 +9,17 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <sys/time.h>
#include <const.h>
#include <errno.h>
#include <sys/time.h>
#include <signal.h>
/*
......@@ -34,18 +35,6 @@
* task.
*/
typedef struct {
struct task_struct * old_task;
struct task_struct ** wait_address;
} wait_entry;
typedef struct select_table_struct {
int nr, woken;
struct task_struct * current;
struct select_table_struct * next_table;
wait_entry entry[NR_OPEN*3];
} select_table;
static select_table * sel_tables = NULL;
static void add_wait(struct task_struct ** wait_address, select_table * p)
......@@ -138,6 +127,11 @@ static int check_in(select_table * wait, struct inode * inode)
return 1;
else
add_wait(&inode->i_wait, wait);
else if (S_ISSOCK(inode->i_mode))
if (sock_select(inode, NULL, SEL_IN, wait))
return 1;
else
add_wait(&inode->i_wait, wait);
return 0;
}
......@@ -155,6 +149,11 @@ static int check_out(select_table * wait, struct inode * inode)
return 1;
else
add_wait(&inode->i_wait, wait);
else if (S_ISSOCK(inode->i_mode))
if (sock_select(inode, NULL, SEL_OUT, wait))
return 1;
else
add_wait(&inode->i_wait, wait);
return 0;
}
......@@ -172,6 +171,11 @@ static int check_ex(select_table * wait, struct inode * inode)
return 1;
else
add_wait(&inode->i_wait,wait);
else if (S_ISSOCK(inode->i_mode))
if (sock_select(inode, NULL, SEL_EX, wait))
return 1;
else
add_wait(&inode->i_wait, wait);
return 0;
}
......@@ -197,6 +201,8 @@ int do_select(fd_set in, fd_set out, fd_set ex,
continue;
if (S_ISFIFO(current->filp[i]->f_inode->i_mode))
continue;
if (S_ISSOCK(current->filp[i]->f_inode->i_mode))
continue;
return -EBADF;
}
repeat:
......@@ -207,6 +213,7 @@ int do_select(fd_set in, fd_set out, fd_set ex,
sel_tables = &wait_table;
*inp = *outp = *exp = 0;
count = 0;
current->state = TASK_INTERRUPTIBLE;
mask = 1;
for (i = 0 ; i < NR_OPEN ; i++, mask += mask) {
if (mask & in)
......@@ -227,14 +234,12 @@ int do_select(fd_set in, fd_set out, fd_set ex,
}
if (!(current->signal & ~current->blocked) &&
current->timeout && !count) {
current->state = TASK_INTERRUPTIBLE;
sti();
schedule();
cli();
free_wait(&wait_table);
goto repeat;
}
free_wait(&wait_table);
current->state = TASK_RUNNING;
return count;
}
......@@ -277,13 +282,11 @@ int sys_select( unsigned long *buffer )
timeout += jiffies;
}
current->timeout = timeout;
cli();
i = do_select(in, out, ex, &res_in, &res_out, &res_ex);
if (current->timeout > jiffies)
timeout = current->timeout - jiffies;
else
timeout = 0;
sti();
current->timeout = 0;
if (i < 0)
return i;
......
......@@ -12,6 +12,7 @@
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <errno.h>
#include <sys/stat.h>
......@@ -146,7 +147,9 @@ int sys_umount(char * dev_name)
struct super_block * sb;
int dev;
if (!(inode=namei(dev_name)))
if (!suser())
return -EPERM;
if (!(inode = namei(dev_name)))
return -ENOENT;
dev = inode->i_rdev;
if (!S_ISBLK(inode->i_mode)) {
......@@ -176,13 +179,17 @@ int sys_umount(char * dev_name)
return 0;
}
int sys_mount(char * dev_name, char * dir_name, int rw_flag)
int sys_mount(char * dev_name, char * dir_name, char * type, int rw_flag)
{
struct inode * dev_i, * dir_i;
struct super_block * sb;
int dev;
char tmp[100],*t;
int i;
if (!(dev_i=namei(dev_name)))
if (!suser())
return -EPERM;
if (!(dev_i = namei(dev_name)))
return -ENOENT;
dev = dev_i->i_rdev;
if (!S_ISBLK(dev_i->i_mode)) {
......@@ -204,7 +211,14 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dir_i);
return -EPERM;
}
if (!(sb=read_super(dev,"minix",NULL))) {
if (type) {
i = 0;
while (i < 100 && (tmp[i] = get_fs_byte(type++)))
i++;
t = tmp;
} else
t = "minix";
if (!(sb = read_super(dev,t,NULL))) {
iput(dir_i);
return -EBUSY;
}
......
#ifndef _ASM_IO_H
#define _ASM_IO_H
/*
* Thanks to James van Artsdalen for a better timing-fix than
* the two short jumps: using outb's to a nonexistent port seems
* to guarantee better timings even on fast machines.
*
* Linus
*/
extern void inline outb(char value, unsigned short port)
{
__asm__ volatile ("outb %0,%1"
......@@ -9,12 +17,11 @@ __asm__ volatile ("outb %0,%1"
extern void inline outb_p(char value, unsigned short port)
{
__asm__ volatile ("outb %0,%1\n"
"\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:"
__asm__ volatile ("outb %0,%1\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80"
::"a" ((char) value),"d" ((unsigned short) port));
}
......@@ -29,12 +36,11 @@ __asm__ volatile ("inb %1,%0"
extern unsigned char inline inb_p(unsigned short port)
{
unsigned char _v;
__asm__ volatile ("inb %1,%0\n"
"\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:"
__asm__ volatile ("inb %1,%0\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80\n\t"
"outb %0,$0x80"
:"=a" (_v):"d" ((unsigned short) port));
return _v;
}
......
......@@ -50,7 +50,7 @@ __asm__ ("movw %%dx,%%ax\n\t" \
((limit) & 0x0ffff); }
#define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \
__asm__ ("movw $232,%1\n\t" \
"movw %%ax,%2\n\t" \
"rorl $16,%%eax\n\t" \
"movb %%al,%3\n\t" \
......
......@@ -16,7 +16,6 @@
extern int errno;
#define ERROR 99
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
......
#ifndef _CONFIG_DIST_H
#define _CONFIG_DIST_H
#ifdef CONFIG_DISTRIBUTION
#undef CONFG_SCSI
#define CONFIG_SCSI
#undef CONFIG_SCSI_AHA1542
#define CONFIG_SCSI_AHA1542
#undef CONFIG_SCSI_CSC
#define CONFIG_SCSI_CSC
#undef CONFIG_SCSI_DTC
#define CONFIG_SCSI_DTC
#undef CONFIG_SCSI_FUTURE_DOMAIN
#define CONFIG_SCSI_FUTURE_DOMAIN
#undef CONFIG_SCSI_SEAGATE
#define CONFIG_SCSI_SEAGATE
#undef CONFIG_SCSI_ULTRASTOR
#define CONFIG_SCSI_ULTRASTOR
#undef CONFIG_BLK_DEV_SD
#define CONFIG_BLK_DEV_SD
#undef CONFIG_BLK_DEV_ST
#define CONFIG_BLK_DEV_ST
#endif
#endif
#ifndef _CONFIG_H
#define _CONFIG_H
#define CONFIG_DISTRIBUTION
/*
* Defines for what uname() should return
*/
......@@ -62,4 +64,52 @@
leave HD_TYPE undefined. This is the normal thing to do.
*/
#undef HD_TYPE
#undef CONFIG_BLK_DEV_SD
#undef CONFIG_BLK_DEV_ST
/*
Choose supported SCSI adapters here.
*/
#undef CONFIG_SCSI_AHA1542
#undef CONFIG_SCSI_ALWAYS
#undef CONFIG_SCSI_CSC
#undef CONFIG_SCSI_DTC
#undef CONFIG_SCSI_FUTURE_DOMAIN
#undef CONFIG_SCSI_SEAGATE
#undef CONFIG_SCSI_ULTRASTOR
#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_ST)
#ifndef CONFIG_SCSI
#define CONFIG_SCSI
#endif
#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
!defined(CONFIG_SCSI_FUTURE_DOMAIN) && !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR)
#error Error : SCSI devices enabled, but no low level drivers have been enabled.
#endif
#endif
#ifdef CONFIG_DISTRIBUTION
#include <linux/config.dist.h>
#else
#include <linux/config.site.h>
#endif
/*
File type specific stuff goes into this.
*/
#ifdef ASM_SRC
#endif
#ifdef C_SRC
#endif
#ifdef MAKE
#endif
#endif
#ifndef _CONFIG_SITE_H
#define _CONFIG_SITE_H
/*
This configuration file contains site specific things, things
that you have added and config.dist will not know about.
*/
#endif
#define UTS_RELEASE "0.95c-18"
#define UTS_RELEASE "0.96a-10"
#define UTS_VERSION "04/09/92"
#define UTS_VERSION "05/22/92"
#ifndef _FD_H_
#define _FD_H
#define FDCLRPRM 0 /* clear user-defined parameters */
#define FDSETPRM 1 /* set user-defined parameters for current media */
#define FDDEFPRM 2 /* set user-defined parameters until explicitly cleared */
#define FDGETPRM 3 /* get disk parameters */
#define FDMSGON 4 /* issue kernel messages on media type change */
#define FDMSGOFF 5 /* don't issue kernel messages on media type change */
#define FDFMTBEG 6 /* begin formatting a disk */
#define FDFMTTRK 7 /* format the specified track */
#define FDFMTEND 8 /* end formatting a disk */
#define FD_FILL_BYTE 0xF6 /* format fill byte */
#define FORMAT_NONE 0 /* no format request */
#define FORMAT_WAIT 1 /* format request is waiting */
#define FORMAT_BUSY 2 /* formatting in progress */
#define FORMAT_OKAY 3 /* successful completion */
#define FORMAT_ERROR 4 /* formatting error */
struct floppy_struct {
unsigned int size, sect, head, track, stretch;
unsigned char gap,rate,spec1,fmt_gap;
char *name; /* used only for predefined formats */
};
struct format_descr {
unsigned int device,head,track;
};
#endif
......@@ -63,6 +63,7 @@ extern void floppy_deselect(unsigned int nr);
#define FD_WRITE 0xC5 /* write with MT, MFM */
#define FD_SENSEI 0x08 /* Sense Interrupt Status */
#define FD_SPECIFY 0x03 /* specify HUT etc */
#define FD_FORMAT 0x4D /* format one track */
/* DMA commands */
#define DMA_READ 0x46
......
......@@ -20,9 +20,11 @@
* 5 - /dev/tty
* 6 - /dev/lp
* 7 - unnamed pipes
* 8 - /dev/sd
* 9 - /dev/st
*/
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3 || (x)==8)
#define MAY_EXEC 1
#define MAY_WRITE 2
......@@ -46,6 +48,9 @@ void buffer_init(long buffer_end);
#define NR_BUFFERS nr_buffers
#define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10
#define MAX_CHRDEV 16
#define MAX_BLKDEV 16
#ifndef NULL
#define NULL ((void *) 0)
#endif
......@@ -78,6 +83,7 @@ struct buffer_head {
struct buffer_head * b_next;
struct buffer_head * b_prev_free;
struct buffer_head * b_next_free;
struct buffer_head * b_reqnext;
};
struct inode {
......@@ -110,11 +116,24 @@ struct file {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
unsigned short f_reada;
struct inode * f_inode;
struct file_operations * f_op;
off_t f_pos;
};
typedef struct {
struct task_struct * old_task;
struct task_struct ** wait_address;
} wait_entry;
typedef struct select_table_struct {
int nr, woken;
struct task_struct * current;
struct select_table_struct * next_table;
wait_entry entry[NR_OPEN*3];
} select_table;
struct super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
......@@ -143,10 +162,15 @@ struct file_operations {
int (*lseek) (struct inode *, struct file *, off_t, int);
int (*read) (struct inode *, struct file *, char *, int);
int (*write) (struct inode *, struct file *, char *, int);
int (*readdir) (struct inode *, struct file *, struct dirent *);
int (*readdir) (struct inode *, struct file *, struct dirent *, int count);
int (*select) (struct inode *, struct file *, int, select_table *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned int);
int (*open) (struct inode *, struct file *);
void (*release) (struct inode *, struct file *);
};
struct inode_operations {
struct file_operations * default_file_ops;
int (*create) (struct inode *,const char *,int,int,struct inode **);
int (*lookup) (struct inode *,const char *,int,struct inode **);
int (*link) (struct inode *,struct inode *,const char *,int);
......@@ -157,18 +181,15 @@ struct inode_operations {
int (*mknod) (struct inode *,const char *,int,int,int);
int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int);
int (*readlink) (struct inode *,char *,int);
int (*open) (struct inode *, struct file *);
void (*release) (struct inode *, struct file *);
struct inode * (*follow_link) (struct inode *, struct inode *);
int (*bmap) (struct inode *,int);
void (*truncate) (struct inode *);
/* added by entropy */
void (*write_inode)(struct inode *inode);
void (*put_inode)(struct inode *inode);
};
struct super_operations {
void (*read_inode)(struct inode *inode);
void (*write_inode) (struct inode *inode);
void (*put_inode) (struct inode *inode);
void (*put_super)(struct super_block *sb);
};
......@@ -177,6 +198,9 @@ struct file_system_type {
char *name;
};
extern struct file_operations * chrdev_fops[MAX_CHRDEV];
extern struct file_operations * blkdev_fops[MAX_BLKDEV];
extern struct file_system_type *get_fs_type(char *name);
extern struct inode inode_table[NR_INODE];
......@@ -190,7 +214,6 @@ extern int floppy_change(struct buffer_head * first_block);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
extern void truncate(struct inode * inode);
extern void sync_inodes(void);
extern void wait_on(struct inode * inode);
extern int bmap(struct inode * inode,int block);
......@@ -222,11 +245,9 @@ extern void mount_root(void);
extern void lock_super(struct super_block * sb);
extern void free_super(struct super_block * sb);
extern int pipe_read(struct inode *, struct file *, char *, int);
extern int char_read(struct inode *, struct file *, char *, int);
extern int block_read(struct inode *, struct file *, char *, int);
extern int pipe_write(struct inode *, struct file *, char *, int);
extern int char_write(struct inode *, struct file *, char *, int);
extern int block_write(struct inode *, struct file *, char *, int);
......
......@@ -4,10 +4,7 @@
void verify_area(void * addr,int count);
volatile void panic(const char * str);
volatile void do_exit(long error_code);
int printf(const char * fmt, ...);
int printk(const char * fmt, ...);
void console_print(const char * str);
int tty_write(unsigned ch,char * buf,int count);
void * malloc(unsigned int size);
void free_s(void * obj, int size);
......
......@@ -31,9 +31,7 @@
#define LP_B(minor) lp_table[(minor)].base
#define LP_F(minor) lp_table[(minor)].flags
#define LP_T(minor) lp_table[(minor)].lp_task
#define LP_S(minor) inb(LP_B((minor)) + 1)
#define LP_R(minor) lp_table[(minor)].remainder
/*
since we are dealing with a horribly slow device
......@@ -45,10 +43,6 @@ I don't see the need for a queue
struct lp_struct {
int base;
int flags;
/* number of characters yet to be printed in current block */
int remainder;
/* needed for busy determination */
int lp_task;
};
/*
......@@ -107,8 +101,3 @@ struct lp_struct lp_table[] = {
*/
extern void lp_init(void);
extern int lp_reset(int minor);
extern int lp_char(char lpchar, int minor);
extern int lp_write(unsigned minor, char *buf, int count);
......@@ -45,7 +45,6 @@ struct minix_dir_entry {
extern int minix_open(struct inode * inode, struct file * filp);
extern void minix_release(struct inode * inode, struct file * filp);
extern struct inode * minix_follow_link(struct inode * dir, struct inode * inode);
extern int minix_lookup(struct inode * dir,const char * name, int len,
struct inode ** result);
extern int minix_create(struct inode * dir,const char * name, int len, int mode,
......@@ -59,29 +58,33 @@ extern int minix_link(struct inode * oldinode, struct inode * dir, const char *
extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
extern int minix_readlink(struct inode * inode, char * buffer, int buflen);
extern struct inode * minix_new_inode(int dev);
extern void minix_free_inode(struct inode * inode);
extern int minix_new_block(int dev);
extern int minix_free_block(int dev, int block);
extern int minix_create_block(struct inode * inode, int block);
extern int minix_bmap(struct inode * inode,int block);
extern int minix_create_block(struct inode *, int);
extern int minix_bmap(struct inode *,int);
extern void minix_truncate(struct inode * inode);
extern void minix_put_super(struct super_block *sb);
extern struct super_block *minix_read_super(struct super_block *s,void *data);
extern void minix_read_inode(struct inode * inode);
extern void minix_write_inode(struct inode * inode);
extern void minix_truncate(struct inode *);
extern void minix_put_super(struct super_block *);
extern struct super_block *minix_read_super(struct super_block *,void *);
extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *);
extern void minix_put_inode(struct inode *);
extern int minix_lseek(struct inode * inode, struct file * filp, off_t offset, int origin);
extern int minix_read(struct inode * inode, struct file * filp, char * buf, int count);
extern int minix_write(struct inode * inode, struct file * filp, char * buf, int count);
extern int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent);
extern int minix_lseek(struct inode *, struct file *, off_t, int);
extern int minix_read(struct inode *, struct file *, char *, int);
extern int minix_write(struct inode *, struct file *, char *, int);
extern int minix_file_read(struct inode *, struct file *, char *, int);
extern int minix_file_write(struct inode *, struct file *, char *, int);
extern struct inode_operations minix_inode_operations;
extern struct inode_operations minix_file_inode_operations;
extern struct inode_operations minix_dir_inode_operations;
extern struct inode_operations minix_symlink_inode_operations;
extern struct inode_operations minix_chrdev_inode_operations;
extern struct inode_operations minix_blkdev_inode_operations;
extern struct file_operations minix_file_operations;
extern struct file_operations minix_dir_operations;
#endif
......@@ -7,6 +7,11 @@
#define TASK_SIZE 0x04000000
#define LIBRARY_SIZE 0x00400000
/*
* Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
*/
#define IO_BITMAP_SIZE 32
#if (TASK_SIZE & 0x3fffff)
#error "TASK_SIZE must be multiple of 4M"
#endif
......@@ -53,6 +58,8 @@
#define NULL ((void *) 0)
#endif
#define MAX_SHARED_LIBS 6
extern int copy_page_tables(unsigned long from, unsigned long to, long size);
extern int free_page_tables(unsigned long from, unsigned long size);
......@@ -60,7 +67,6 @@ extern void sched_init(void);
extern void schedule(void);
extern void trap_init(void);
extern void panic(const char * str);
extern int tty_write(unsigned minor,char * buf,int count);
typedef int (*fn_ptr)();
......@@ -76,29 +82,30 @@ struct i387_struct {
};
struct tss_struct {
long back_link; /* 16 high bits zero */
long esp0;
long ss0; /* 16 high bits zero */
long esp1;
long ss1; /* 16 high bits zero */
long esp2;
long ss2; /* 16 high bits zero */
long cr3;
long eip;
long eflags;
long eax,ecx,edx,ebx;
long esp;
long ebp;
long esi;
long edi;
long es; /* 16 high bits zero */
long cs; /* 16 high bits zero */
long ss; /* 16 high bits zero */
long ds; /* 16 high bits zero */
long fs; /* 16 high bits zero */
long gs; /* 16 high bits zero */
long ldt; /* 16 high bits zero */
long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
unsigned long back_link; /* 16 high bits zero */
unsigned long esp0;
unsigned long ss0; /* 16 high bits zero */
unsigned long esp1;
unsigned long ss1; /* 16 high bits zero */
unsigned long esp2;
unsigned long ss2; /* 16 high bits zero */
unsigned long cr3;
unsigned long eip;
unsigned long eflags;
unsigned long eax,ecx,edx,ebx;
unsigned long esp;
unsigned long ebp;
unsigned long esi;
unsigned long edi;
unsigned long es; /* 16 high bits zero */
unsigned long cs; /* 16 high bits zero */
unsigned long ss; /* 16 high bits zero */
unsigned long ds; /* 16 high bits zero */
unsigned long fs; /* 16 high bits zero */
unsigned long gs; /* 16 high bits zero */
unsigned long ldt; /* 16 high bits zero */
unsigned long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
unsigned long io_bitmap[IO_BITMAP_SIZE];
struct i387_struct i387;
};
......@@ -143,9 +150,14 @@ struct task_struct {
struct inode * pwd;
struct inode * root;
struct inode * executable;
struct inode * library;
unsigned long close_on_exec;
struct {
struct inode * library;
unsigned long start;
unsigned long length;
} libraries[MAX_SHARED_LIBS];
int numlibraries;
struct file * filp[NR_OPEN];
unsigned long close_on_exec;
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
struct desc_struct ldt[3];
/* tss for this task */
......@@ -183,17 +195,18 @@ struct task_struct {
/* math */ 0, \
/* rss */ 2, \
/* comm */ "swapper", \
/* fs info */ 0,-1,0022,NULL,NULL,NULL,NULL,0, \
/* filp */ {NULL,}, \
{ \
{0,0}, \
/* ldt */ {0x9f,0xc0fa00}, \
{0x9f,0xc0f200}, \
}, \
/* fs info */ 0,-1,0022,NULL,NULL,NULL, \
/* libraries */ { { NULL, 0, 0}, }, 0, \
/* filp */ {NULL,}, 0, \
{ \
{0,0}, \
/* ldt */ {0x9f,0xc0fa00}, \
{0x9f,0xc0f200} \
}, \
/*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
0,0,0,0,0,0,0,0, \
0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
_LDT(0),0x80000000, \
_LDT(0),0x80000000,{0xffffffff}, \
{} \
}, \
}
......@@ -209,6 +222,7 @@ extern int jiffies_offset;
extern void add_timer(long jiffies, void (*fn)(void));
extern void sleep_on(struct task_struct ** p);
extern int send_sig(long sig,struct task_struct * p,int priv);
extern void interruptible_sleep_on(struct task_struct ** p);
extern void wake_up(struct task_struct ** p);
extern int in_group_p(gid_t grp);
......
......@@ -92,6 +92,20 @@ extern int sys_uselib();
extern int sys_swapon();
extern int sys_reboot();
extern int sys_readdir();
extern int sys_mmap();
extern int sys_munmap();
extern int sys_truncate();
extern int sys_ftruncate();
extern int sys_fchmod();
extern int sys_fchown();
extern int sys_getpriority();
extern int sys_setpriority();
extern int sys_profil();
extern int sys_statfs();
extern int sys_fstatfs();
extern int sys_ioperm();
extern int sys_socketcall();
extern int sys_syslog();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
......@@ -105,10 +119,14 @@ sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday,
sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
sys_lstat, sys_readlink, sys_uselib, sys_swapon, sys_reboot, sys_readdir };
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
sys_gettimeofday, sys_settimeofday, sys_getgroups, sys_setgroups,
sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
sys_socketcall, sys_syslog };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
......@@ -20,6 +20,8 @@
* HD_TIMER harddisk timer
*
* FLOPPY_TIMER floppy disk timer (not used right now)
*
* SCSI_TIMER scsi.c timeout timer
*/
#define BLANK_TIMER 0
......@@ -37,6 +39,7 @@
#define HD_TIMER 16
#define FLOPPY_TIMER 17
#define SCSI_TIMER 18
struct timer_struct {
unsigned long expires;
......
......@@ -9,6 +9,8 @@
#ifndef _TTY_H
#define _TTY_H
#include <asm/system.h>
#define MAX_CONSOLES 8
#define NR_SERIALS 4
#define NR_PTYS 4
......@@ -24,7 +26,7 @@ struct tty_queue {
unsigned long head;
unsigned long tail;
struct task_struct * proc_list;
char buf[TTY_BUF_SIZE];
unsigned char buf[TTY_BUF_SIZE];
};
#define IS_A_CONSOLE(min) (((min) & 0xC0) == 0x00)
......@@ -41,11 +43,31 @@ struct tty_queue {
#define LAST(a) ((a)->buf[(TTY_BUF_SIZE-1)&((a)->head-1)])
#define FULL(a) (!LEFT(a))
#define CHARS(a) (((a)->head-(a)->tail)&(TTY_BUF_SIZE-1))
#define GETCH(queue,c) \
(void)({c=(queue)->buf[(queue)->tail];INC((queue)->tail);})
#define PUTCH(c,queue) \
(void)({(queue)->buf[(queue)->head]=(c);INC((queue)->head);})
static inline void PUTCH(char c, struct tty_queue * queue)
{
int head;
cli();
head = (queue->head + 1) & (TTY_BUF_SIZE-1);
if (head != queue->tail) {
queue->buf[queue->head] = c;
queue->head = head;
}
sti();
}
static inline int GETCH(struct tty_queue * queue)
{
int result = -1;
if (queue->tail != queue->head) {
result = 0xff & queue->buf[queue->tail];
queue->tail = (queue->tail + 1) & (TTY_BUF_SIZE-1);
}
return result;
}
#define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
#define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
......@@ -55,12 +77,43 @@ struct tty_queue {
#define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])
#define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP])
#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
#define L_CANON(tty) _L_FLAG((tty),ICANON)
#define L_ISIG(tty) _L_FLAG((tty),ISIG)
#define L_ECHO(tty) _L_FLAG((tty),ECHO)
#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
#define I_NLCR(tty) _I_FLAG((tty),INLCR)
#define I_CRNL(tty) _I_FLAG((tty),ICRNL)
#define I_NOCR(tty) _I_FLAG((tty),IGNCR)
#define I_IXON(tty) _I_FLAG((tty),IXON)
#define I_STRP(tty) _I_FLAG((tty),ISTRIP)
#define O_POST(tty) _O_FLAG((tty),OPOST)
#define O_NLCR(tty) _O_FLAG((tty),ONLCR)
#define O_CRNL(tty) _O_FLAG((tty),OCRNL)
#define O_NLRET(tty) _O_FLAG((tty),ONLRET)
#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
#define C_SPEED(tty) ((tty)->termios.c_cflag & CBAUD)
#define C_HUP(tty) (C_SPEED((tty)) == B0)
struct tty_struct {
struct termios termios;
int pgrp;
int session;
int stopped;
int busy;
int count;
struct winsize winsize;
void (*write)(struct tty_struct * tty);
struct tty_queue *read_q;
......@@ -103,6 +156,7 @@ do { \
} while (0)
extern struct tty_struct tty_table[];
extern struct tty_struct * redirect;
extern int fg_console;
extern unsigned long video_num_columns;
extern unsigned long video_num_lines;
......@@ -119,17 +173,22 @@ extern unsigned long video_num_lines;
*/
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
void rs_init(void);
void con_init(void);
void tty_init(void);
extern void rs_init(void);
extern void lp_init(void);
extern void con_init(void);
extern void tty_init(void);
extern void flush(struct tty_queue * queue);
int tty_read(unsigned c, char * buf, int n, unsigned short flags);
int tty_write(unsigned c, char * buf, int n);
extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
extern int is_orphaned_pgrp(int pgrp);
extern int is_ignored(int sig);
extern int tty_signal(int sig, struct tty_struct *tty);
void con_write(struct tty_struct * tty);
void rs_write(struct tty_struct * tty);
void mpty_write(struct tty_struct * tty);
void spty_write(struct tty_struct * tty);
extern void rs_write(struct tty_struct * tty);
extern void con_write(struct tty_struct * tty);
extern void mpty_write(struct tty_struct * tty);
extern void spty_write(struct tty_struct * tty);
extern void serial_open(unsigned int line);
......@@ -137,4 +196,6 @@ void copy_to_cooked(struct tty_struct * tty);
void update_screen(int new_console);
int kill_pg(int pgrp, int sig, int priv);
#endif
#ifndef _LINUX_UNISTD_H
#define _LINUX_UNISTD_H
/*
* This file contains the system call numbers and the syscallX
* macros
*/
#define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_stat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_fstat 28
#define __NR_pause 29
#define __NR_utime 30
#define __NR_stty 31
#define __NR_gtty 32
#define __NR_access 33
#define __NR_nice 34
#define __NR_ftime 35
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
#define __NR_mkdir 39
#define __NR_rmdir 40
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
#define __NR_prof 44
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
#define __NR_signal 48
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_phys 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define __NR_mpx 56
#define __NR_setpgid 57
#define __NR_ulimit 58
#define __NR_uname 59
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
#define __NR_dup2 63
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
#define __NR_sigaction 67
#define __NR_sgetmask 68
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_sigsuspend 72
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
#define __NR_symlink 83
#define __NR_lstat 84
#define __NR_readlink 85
#define __NR_uselib 86
#define __NR_swapon 87
#define __NR_reboot 88
#define __NR_readdir 89
#define __NR_mmap 90
#define __NR_munmap 91
#define __NR_truncate 92
#define __NR_ftruncate 93
#define __NR_fchmod 94
#define __NR_fchown 95
/*
* Not all of these are implemented yet, but these are the
* numbers they will use.
*/
#define __NR_getpriority 96
#define __NR_setpriority 97
#define __NR_profil 98
#define __NR_statfs 99
#define __NR_fstatfs 100
#define __NR_ioperm 101
#define __NR_socketcall 102
#define __NR_syslog 103
extern int errno;
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"g" ((long)(a)):"bx"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall2(type,name,atype,a,btype,b) \
type name(atype a,btype b) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)):"bx"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)),"d" ((long)(c)):"bx"); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
type name (atype a, btype b, ctype c, dtype d) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
"d" ((long)(c)),"S" ((long)(d))); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
type name (atype a,btype b,ctype c,dtype d,etype e) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)), \
"d" ((long)(c)),"S" ((long)(d)),"D" ((long)(e))); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
#endif /* _LINUX_UNISTD_H */
#ifndef _KD_H
#define _KD_H
/* 0x4B is 'K', to avoid collision with termios and vt */
#define SWAPMONO 0x4B00 /* use mca as output device */
#define SWAPCGA 0x4B01 /* use cga as output device */
#define SWAPEGA 0x4B02 /* use ega as output device */
#define SWAPVGA 0x4B03 /* use vga as output device */
#define CONS_CURRENT 0x4B04 /* return current output device */
#define MONO 0x01
#define CGA 0x02
#define EGA 0x03
#define SW_B40x25 0x4B05 /* 40x25 mono text (cga/ega) */
#define SW_C40x25 0x4B06 /* 40x24 color text (cga/ega) */
#define SW_B80x25 0x4B07 /* 80x25 mono text (cga/ega) */
#define SW_C80x25 0x4B08 /* 80x25 color text (cga/ega) */
#define SW_BG320 0x4B09 /* 320x200 mono graphics (cga/ega) */
#define SW_CG320 0x4B0A /* 320x200 color graphics (cga/ega) */
#define SW_BG640 0x4B0B /* 640x200 mono graphics (cga/ega) */
#define SW_CG320_D 0x4B0C /* 320x200 graphics (ega mode d) */
#define SW_CG640_E 0x4B0D /* 640x200 graphics (ega mode e) */
#define SW_EGAMONOAPA 0x4B0E /* 640x350 graphics (ega mode f) */
#define SW_ENH_MONOAPA2 0x4B0F /* 640x350 graphics extd mem (ega mode f*) */
#define SW_CG640x350 0x4B10 /* 640x350 graphics (ega mode 10) */
#define SW_ENH_CG640 0x4B11 /* 640x350 graphics extd mem (ega mode 10*) */
#define SW_EGAMONO80x25 0x4B12 /* 80x25 mono text (ega mode 7) */
#define SW_ENHB40x25 0x4B13 /* enhanced 40x25 mono text (ega) */
#define SW_ENHC40x25 0x4B14 /* enhanced 40x25 color text (ega) */
#define SW_ENHB80x25 0x4B15 /* enhanced 80x25 mono text (ega) */
#define SW_ENHC80x25 0x4B16 /* enhanced 80x25 color text (ega) */
#define SW_ENHB80x43 0x4B17 /* enhanced 80x43 mono text (ega) */
#define SW_ENHC80x43 0x4B18 /* enhanced 80x43 color text (ega) */
#define SW_MCAMODE 0x4B19 /* reinit mca */
#define SW_ATT640 0x4B1A /* 640x400 16color */
/* should add more vga modes, etc */
#define CONS_GET 0x4B1B /* get current display mode */
#define M_B40x25 0 /* 40x25 mono (cga/ega) */
#define M_C40x25 1 /* 40x25 color (cga/ega) */
#define M_B80x25 2 /* 80x25 mono (cga/ega) */
#define M_C80x25 3 /* 80x25 color (cga/ega) */
#define M_BG320 4 /* 320x200 mono (cga/ega) */
#define M_CG320 5 /* 320x200 color (cga/ega) */
#define M_BG640 6 /* 640x200 mono (cga/ega) */
#define M_EGAMONO80x25 7 /* 80x25 mono (ega) */
#define M_CG320_D 13 /* ega mode d */
#define M_CG640_E 14 /* ega mode e */
#define M_EFAMONOAPA 15 /* ega mode f */
#define M_CG640x350 16 /* ega mode 10 */
#define M_ENHMONOAPA2 17 /* ega mode f with ext mem */
#define M_ENH_CG640 18 /* ega mode 10* */
#define M_ENH_B40x25 19 /* ega enh 40x25 mono */
#define M_ENH_C40x25 20 /* ega enh 40x25 color */
#define M_ENH_B80x25 21 /* ega enh 80x25 mono */
#define M_ENH_C80x25 22 /* ega enh 80x25 color */
#define M_ENH_B80x43 0x70 /* ega enh 80x43 mono */
#define M_ENH_C80x43 0x71 /* ega enh 80x43 color */
#define M_MCA_MODE 0xff /* monochrome adapter mode */
#define MCA_GET 0x4B1C /* get mca display mode */
#define CGA_GET 0x4B1D /* get cga display mode */
#define EGA_GET 0x4B1E /* get ega display mode */
#define MAPCONS 0x4B1F /* map current video mem into address space */
#define MAPMONO 0x4B20 /* map mca video mem into address space */
#define MAPCGA 0x4B21 /* map cga video mem into address space */
#define MAPEGA 0x4B22 /* map ega video mem into address space */
#define MAPVGA 0x4B23 /* map vga video mem into address space */
struct port_io_struc {
char dir; /* direction in vs out */
unsigned short port;
char data;
};
#define IN_ON_PORT 0x00
#define OUT_ON_PORT 0x01
struct port_io_arg {
struct port_io_struc args[4];
};
#define MCAIO 0x4B24 /* i/o to mca video board */
#define CGAIO 0x4B25 /* i/o to cga video board */
#define EGAIO 0x4B26 /* i/o to ega video board */
#define VGAIO 0x4B27 /* i/o to vga video board */
#define GIO_FONT8x8 0x4B28 /* gets current 8x8 font used */
#define PIO_FONT8x8 0x4B29 /* use supplied 8x8 font */
#define GIO_FONT8x14 0x4B2A /* gets current 8x14 font used */
#define PIO_FONT8x14 0x4B2B /* use supplied 8x14 font */
#define GIO_FONT8x16 0x4B2C /* gets current 8x16 font used */
#define PIO_FONT8x16 0x4B2D /* use supplied 8x16 font */
#define MKDIOADDR 32 /* io bitmap size from <linux/sched.h> */
struct kd_disparam {
long type; /* type of display */
char *addr; /* display mem address */
ushort ioaddr[MKDIOADDR]; /* valid i/o addresses */
};
#define KDDISPTYPE 0x4B2E /* gets display info */
#define KD_MONO 0x01
#define KD_HERCULES 0x02
#define KD_CGA 0x03
#define KD_EGA 0x04
#define KIOCSOUND 0x4B2F /* start sound generation (0 for off) */
#define KDMKTONE 0x4B30 /* generate tone */
#define KDGETLED 0x4B31 /* return current led flags */
#define KDSETLED 0x4B32 /* set current led flags */
#define LED_SCR 0x01 /* scroll lock */
#define LED_CAP 0x04 /* caps lock */
#define LED_NUM 0x02 /* num lock */
#define KDGKBTYPE 0x4B33 /* get keyboard type */
#define KB_84 0x01
#define KB_101 0x02
#define KB_OTHER 0x03
#define KDADDIO 0x4B34 /* add i/o port as valid */
#define KDDELIO 0x4B35 /* del i/o port as valid */
#define KDENABIO 0x4B36 /* enable i/o to video board */
#define KDDISABIO 0x4B37 /* disable i/o to video board */
struct kd_quemode {
int qsize; /* desired # elem in queue */
int signo; /* signal to send when queue not empty */
char *qaddr; /* user virt addr of queue */
};
#define KDQUEMODE 0x4B38 /* enable/disable special queue mode */
#define KDSBORDER 0x4B39 /* set screen boarder in ega text mode */
#define KDSETMODE 0x4B3A /* set text/grahics mode */
#define KD_TEXT 0x00
#define KD_GRAPHICS 0x01
#define KD_TEXT0 0x02 /* ? */
#define KD_TEXT1 0x03 /* ? */
#define KDGETMODE 0x4B3B /* get current mode */
struct kd_memloc {
char *vaddr; /* virt addr to map to */
char *physaddr; /* phys addr to map from */
long length; /* number of bytes */
long ioflg; /* enable i/o if set */
};
#define KDMAPDISP 0x4B3C /* map display into address space */
#define KDUNMAPDISP 0x4B3D /* unmap display from address space */
#define KDVDCTYPE 0x4B3E /* return vdc controller/display info */
#define KIOCINFO 0x4B3F /* tell what the device is */
typedef char scrnmap_t;
#define E_TABSZ 256
#define GIO_SCRNMAP 0x4B40 /* get screen mapping from kernel */
#define PIO_SCRNMAP 0x4B41 /* put screen mapping table in kernel */
#define GIO_ATTR 0x4B42 /* get screen attributes */
#define GIO_COLOR 0x4B43 /* return nonzero if display is color */
#define K_RAW 0x00
#define K_XLATE 0x01
#define KDGKBMODE 0x4B44 /* gets current keyboard mode */
#define KDSKBMODE 0x4B45 /* sets current keyboard mode */
struct kbentry {
u_char kb_table;
u_char kb_index;
u_char kb_value;
};
#define K_NORMTAB 0x00
#define K_SHIFTTAB 0x01
#define K_ALTTAB 0x02
#define K_ALTSHIFTTAB 0x03
#define K_SRQTAB 0x04
#define KDGKBENT 0x4B46 /* gets one entry in translation table */
#define KDSKBENT 0x4B47 /* sets one entry in translation table */
#endif /* _KD_H */
#ifndef _MMAN_H
#define _MMAN_H
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
#define PROT_NONE 0x0 /* page can not be accessed */
#define MAP_SHARED 1 /* Share changes */
#define MAP_PRIVATE 2 /* Changes are private */
#define MAP_TYPE 0xf /* Mask for type of mapping */
#define MAP_FIXED 0x10 /* Interpret addr exactly */
extern caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd,
off_t off);
extern int munmap(caddr_t addr, size_t len);
#endif /* _MMAN_H */
......@@ -60,4 +60,11 @@ struct rlimit {
int rlim_max;
};
#define PRIO_MIN -99
#define PRIO_MAX 14
#define PRIO_PROCESS 0
#define PRIO_PGRP 1
#define PRIO_USER 2
#endif /* _SYS_RESOURCE_H */
#ifndef _SOCKET_H
#define _SOCKET_H
struct sockaddr {
u_short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
/*
* socket types
*/
#define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (connectionless) socket */
#define SOCK_SEQPACKET 3 /* sequential packet socket */
#define SOCK_RAW 4 /* raw socket */
/*
* supported address families
*/
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_INET 2
/*
* protocol families, same as address families
*/
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
int socket(int family, int type, int protocol);
int socketpair(int family, int type, int protocol, int sockvec[2]);
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *peer, int *paddrlen);
int getsockname(int sockfd, struct sockaddr *addr, int *paddrlen);
int getpeername(int sockfd, struct sockaddr *peer, int *paddrlen);
#endif /* _SOCKET_H */
......@@ -18,6 +18,7 @@ struct stat {
};
#define S_IFMT 00170000
#define S_IFSOCK 0140000
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFBLK 0060000
......@@ -34,6 +35,7 @@ struct stat {
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#define S_IRWXU 00700
#define S_IRUSR 00400
......
......@@ -31,6 +31,8 @@ typedef unsigned short nlink_t;
typedef int daddr_t;
typedef long off_t;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
typedef unsigned short ushort;
typedef char *caddr_t;
......
#ifndef _UN_H
#define _UN_H
struct sockaddr_un {
u_short sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
#endif /* _UN_H */
#ifndef _SYS_VFS_H_
#define _SYS_VFS_H_
typedef struct {
long val[2];
} fsid_t;
struct statfs {
long f_type;
long f_bsize;
long f_blocks;
long f_bfree;
long f_bavail;
long f_files;
long f_ffree;
fsid_t f_fsid;
long f_spare[7];
};
#endif
#ifndef _VT_H
#define _VT_H
/* 0x56 is 'V', to avoid collision with termios and kd */
#define VT_OPENQRY 0x5600 /* find available vt */
struct vt_mode {
char mode; /* vt mode */
char waitv; /* if set, hang on writes if not active */
short relsig; /* signal to raise on release req */
short acqsig; /* signal to raise on acquisition */
short frsig; /* unused (set to 0) */
};
#define VT_GETMODE 0x5601 /* get mode of active vt */
#define VT_SETMODE 0x5602 /* set mode of active vt */
#define VT_AUTO 0x00 /* auto vt switching */
#define VT_PROCESS 0x01 /* process controls switching */
struct vt_stat {
ushort v_active; /* active vt */
ushort v_signal; /* signal to send */
ushort v_state; /* vt bitmask */
};
#define VT_GETSTATE 0x5603 /* get global vt state info */
#define VT_SENDSIG 0x5604 /* signal to send to bitmask of vts */
#define VT_RELDISP 0x5605 /* release display */
#define VT_ACTIVATE 0x5606 /* make vt active */
#endif /* _VT_H */
......@@ -34,6 +34,7 @@
#define FIONREAD 0x541B
#define TIOCINQ FIONREAD
#define TIOCLINUX 0x541C
#define TIOCCONS 0x541D
struct winsize {
unsigned short ws_row;
......
......@@ -64,154 +64,7 @@
#include <utime.h>
#ifdef __LIBRARY__
#define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_stat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_fstat 28
#define __NR_pause 29
#define __NR_utime 30
#define __NR_stty 31
#define __NR_gtty 32
#define __NR_access 33
#define __NR_nice 34
#define __NR_ftime 35
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
#define __NR_mkdir 39
#define __NR_rmdir 40
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
#define __NR_prof 44
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
#define __NR_signal 48
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_phys 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define __NR_mpx 56
#define __NR_setpgid 57
#define __NR_ulimit 58
#define __NR_uname 59
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
#define __NR_dup2 63
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
#define __NR_sigaction 67
#define __NR_sgetmask 68
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_sigsuspend 72
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
#define __NR_symlink 83
#define __NR_lstat 84
#define __NR_readlink 85
#define __NR_uselib 86
#define __NR_swapon 87
#define __NR_reboot 88
#define __NR_readdir 89
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"g" ((long)(a)):"bx"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall2(type,name,atype,a,btype,b) \
type name(atype a,btype b) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)):"bx"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
long __res; \
__asm__ volatile ("movl %2,%%ebx\n\t" \
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"g" ((long)(a)),"c" ((long)(b)),"d" ((long)(c)):"bx"); \
if (__res>=0) \
return (type) __res; \
errno=-__res; \
return -1; \
}
#include <linux/unistd.h>
#endif /* __LIBRARY__ */
/* XXX - illegal. */
......@@ -255,7 +108,7 @@ int kill(pid_t pid, int signal);
int link(const char * filename1, const char * filename2);
off_t lseek(int fildes, off_t offset, int origin);
int mknod(const char * filename, mode_t mode, dev_t dev); /* XXX - shorts */
int mount(const char * specialfile, const char * dir, int rwflag);
int mount(const char * specialfile, const char * dir, const char * type, int rwflag);
int nice(int val);
int open(const char * filename, int flag, ...);
int pause(void);
......
......@@ -4,10 +4,22 @@
* (C) 1991 Linus Torvalds
*/
#define __LIBRARY__
#include <unistd.h>
#include <stddef.h>
#include <stdarg.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <asm/system.h>
#include <asm/io.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/head.h>
#include <linux/unistd.h>
/*
* we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This
......@@ -24,36 +36,35 @@ static inline _syscall0(int,fork)
static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS)
static inline _syscall0(int,sync)
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <asm/system.h>
#include <asm/io.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <string.h>
static inline _syscall0(pid_t,setsid)
static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
static inline _syscall1(int,dup,int,fd)
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
static inline _syscall1(int,close,int,fd)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}
static char printbuf[1024];
extern char *strcpy();
extern int vsprintf();
extern void init(void);
extern void blk_dev_init(void);
extern void chr_dev_init(void);
extern void hd_init(void);
extern void floppy_init(void);
extern void sock_init(void);
extern void mem_init(long start, long end);
extern long rd_init(long mem_start, int length);
extern long kernel_mktime(struct tm * tm);
#ifdef CONFIG_SCSI
extern void scsi_dev_init(void);
#endif
static int sprintf(char * str, const char *fmt, ...)
{
va_list args;
......@@ -156,15 +167,19 @@ void start_kernel(void)
#endif
mem_init(main_memory_start,memory_end);
trap_init();
blk_dev_init();
sched_init();
chr_dev_init();
tty_init();
blk_dev_init();
time_init();
sched_init();
printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n");
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
sock_init();
sti();
#ifdef CONFIG_SCSI
scsi_dev_init();
#endif
move_to_user_mode();
if (!fork()) { /* we count on this going ok */
init();
......
......@@ -15,6 +15,8 @@ CC =gcc -nostdinc -I../include
CPP =cpp -nostdinc -I../include
.S.s:
$(CPP) -traditional $< -o $*.s
.c.s:
$(CC) $(CFLAGS) \
-S -o $*.s $<
......@@ -26,17 +28,21 @@ CPP =cpp -nostdinc -I../include
OBJS = sched.o sys_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o ptrace.o
signal.o mktime.o ptrace.o ioport.o
kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS)
sync
sys_call.s: sys_call.S
sys_call.o: sys_call.s
sched.o: sched.c
$(CC) $(CFLAGS) -fno-omit-frame-pointer -c $<
clean:
rm -f core *.o *.a tmp_make keyboard.s
rm -f core *.o *.a tmp_make sys_call.s
for i in *.c;do rm -f `basename $$i .c`.s;done
(cd chr_drv; make clean)
(cd blk_drv; make clean)
......@@ -49,61 +55,59 @@ dep:
cp tmp_make Makefile
(cd chr_drv; make dep)
(cd blk_drv; make dep)
(cd math; make dep)
### Dependencies:
exit.s exit.o : exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/dirent.h \
../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
../include/sys/param.h ../include/sys/time.h ../include/time.h \
../include/sys/resource.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h
fork.s fork.o : fork.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h \
exit.s exit.o : exit.c ../include/errno.h ../include/signal.h ../include/sys/types.h \
../include/sys/wait.h ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/linux/tty.h ../include/asm/system.h ../include/termios.h ../include/asm/segment.h
fork.s fork.o : fork.c ../include/errno.h ../include/stddef.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
../include/sys/param.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/asm/segment.h ../include/asm/system.h
ioport.s ioport.o : ioport.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/errno.h
mktime.s mktime.o : mktime.c ../include/time.h
panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \
panic.s panic.o : panic.c ../include/linux/kernel.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
../include/linux/mm.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h
printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h \
../include/linux/kernel.h
ptrace.s ptrace.o : ptrace.c ../include/linux/head.h ../include/linux/kernel.h \
../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/errno.h \
../include/asm/segment.h ../include/asm/system.h ../include/sys/ptrace.h
sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/linux/timer.h \
../include/linux/sys.h ../include/linux/fdreg.h ../include/asm/system.h \
../include/asm/io.h ../include/asm/segment.h ../include/errno.h
signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h \
../include/limits.h ../include/linux/mm.h ../include/linux/kernel.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
../include/sys/wait.h ../include/errno.h
sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/linux/tty.h ../include/termios.h ../include/linux/config.h \
../include/asm/segment.h ../include/sys/times.h ../include/sys/utsname.h \
../include/string.h
traps.s traps.o : traps.c ../include/string.h ../include/linux/head.h \
../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h \
printk.s printk.o : printk.c ../include/stdarg.h ../include/stddef.h ../include/errno.h \
../include/asm/segment.h ../include/asm/system.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h
ptrace.s ptrace.o : ptrace.c ../include/linux/head.h ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
../include/linux/mm.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/errno.h ../include/asm/segment.h \
../include/asm/system.h ../include/sys/ptrace.h
sched.s sched.o : sched.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/linux/timer.h ../include/linux/sys.h \
../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h ../include/asm/segment.h \
../include/errno.h
signal.s signal.o : signal.c ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/sys/types.h ../include/sys/dirent.h ../include/limits.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.h ../include/sys/wait.h \
../include/errno.h
vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/string.h
sys.s sys.o : sys.c ../include/errno.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/linux/tty.h \
../include/asm/system.h ../include/termios.h ../include/linux/config.h ../include/linux/config_rel.h \
../include/linux/config_ver.h ../include/linux/config.dist.h ../include/asm/segment.h \
../include/sys/times.h ../include/sys/utsname.h ../include/linux/string.h
traps.s traps.o : traps.c ../include/linux/string.h ../include/linux/head.h ../include/linux/sched.h \
../include/linux/fs.h ../include/sys/types.h ../include/sys/dirent.h ../include/limits.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h ../include/asm/system.h \
../include/asm/segment.h ../include/asm/io.h ../include/errno.h
vsprintf.s vsprintf.o : vsprintf.c ../include/stdarg.h ../include/linux/string.h
......@@ -5,138 +5,47 @@
*/
/*
* asm.s contains the low-level code for most hardware faults.
* page_exception is handled by the mm, so that isn't here. This
* file also handles (hopefully) fpu-exceptions due to TS-bit, as
* the fpu must be properly saved/resored. This hasn't been tested.
* asm.s contains the low-level code for interrupts that cannot
* result in an task-switch. These are things like the hd- and
* floppy-interrupt etc. With these interrupts, we don't have to
* care about the stack layout etc.
*/
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_coprocessor_error,_irq13,_reserved
.globl _alignment_check
.globl _page_fault
.globl _floppy_interrupt,_parallel_interrupt
_divide_error:
pushl $0 # no error code
pushl $_do_divide_error
error_code:
push %fs
push %es
push %ds
_floppy_interrupt:
cld
pushl %eax
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
cld
movl $-1, %eax
xchgl %eax, 0x2c(%esp) # orig_eax (get the error code. )
xorl %ebx,%ebx # zero ebx
mov %gs,%bx # get the lower order bits of gs
xchgl %ebx, 0x28(%esp) # get the address and save gs.
pushl %eax # push the error code
lea 52(%esp),%edx
pushl %edx
movl $0x10,%edx
mov %dx,%ds
mov %dx,%es
mov %dx,%fs
call *%ebx
addl $8,%esp
popl %ebx
popl %ecx
push %ds
push %es
push %fs
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
movl $0x17,%eax
mov %ax,%fs
movb $0x20,%al
outb %al,$0x20 # EOI to interrupt controller #1
xorl %eax,%eax
xchgl _do_floppy,%eax
testl %eax,%eax
jne 1f
movl $_unexpected_floppy_interrupt,%eax
1: call *%eax # "interesting" way of handling intr.
pop %fs
pop %es
pop %ds
popl %edx
popl %esi
popl %edi
popl %ebp
popl %ecx
popl %eax
pop %ds
pop %es
pop %fs
pop %gs
addl $4,%esp
iret
_debug:
pushl $0
pushl $_do_int3 # _do_debug
jmp error_code
_nmi:
pushl $0
pushl $_do_nmi
jmp error_code
_int3:
pushl $0
pushl $_do_int3
jmp error_code
_overflow:
pushl $0
pushl $_do_overflow
jmp error_code
_bounds:
pushl $0
pushl $_do_bounds
jmp error_code
_invalid_op:
pushl $0
pushl $_do_invalid_op
jmp error_code
_coprocessor_segment_overrun:
pushl $0
pushl $_do_coprocessor_segment_overrun
jmp error_code
_reserved:
pushl $0
pushl $_do_reserved
jmp error_code
_irq13:
_parallel_interrupt:
cld
pushl %eax
xorb %al,%al
outb %al,$0xF0
movb $0x20,%al
outb %al,$0x20
jmp 1f
1: jmp 1f
1: outb %al,$0xA0
popl %eax
jmp _coprocessor_error
_double_fault:
pushl $_do_double_fault
jmp error_code
_invalid_TSS:
pushl $_do_invalid_TSS
jmp error_code
_segment_not_present:
pushl $_do_segment_not_present
jmp error_code
_stack_segment:
pushl $_do_stack_segment
jmp error_code
_general_protection:
pushl $_do_general_protection
jmp error_code
_alignment_check:
pushl $_do_alignment_check
jmp error_code
_page_fault:
pushl $_do_page_fault
jmp error_code
iret
......@@ -25,15 +25,19 @@ CPP =cpp -nostdinc -I../../include
$(CC) $(CFLAGS) \
-c -o $*.o $<
OBJS = ll_rw_blk.o floppy.o hd.o ramdisk.o
OBJS = hd.o ll_rw_blk.o floppy.o ramdisk.o
all: blk_drv.a
blk_drv.a: $(OBJS)
rm -f blk_drv.a
$(AR) rcs blk_drv.a $(OBJS)
sync
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
(cd scsi; make clean)
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
......@@ -42,36 +46,31 @@ dep:
cp tmp_make Makefile
### Dependencies:
floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/fdreg.h \
../../include/asm/system.h ../../include/asm/io.h \
../../include/asm/segment.h blk.h
hd.s hd.o : hd.c ../../include/errno.h ../../include/linux/config.h \
../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/timer.h \
../../include/linux/hdreg.h ../../include/asm/system.h \
../../include/asm/io.h ../../include/asm/segment.h blk.h
floppy.s floppy.o : floppy.c ../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
../../include/linux/timer.h ../../include/linux/fdreg.h ../../include/linux/fd.h \
../../include/asm/system.h ../../include/asm/io.h ../../include/asm/segment.h \
../../include/errno.h blk.h
hd.s hd.o : hd.c ../../include/errno.h ../../include/linux/config.h ../../include/linux/config_rel.h \
../../include/linux/config_ver.h ../../include/linux/config.dist.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/timer.h ../../include/linux/hdreg.h \
../../include/asm/system.h ../../include/asm/io.h ../../include/asm/segment.h \
blk.h
ll_rw_blk.s ll_rw_blk.o : ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/linux/head.h ../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/asm/system.h blk.h
ramdisk.s ramdisk.o : ramdisk.c ../../include/linux/string.h ../../include/linux/config.h \
../../include/linux/config_rel.h ../../include/linux/config_ver.h ../../include/linux/config.dist.h \
../../include/linux/sched.h ../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/sys/dirent.h ../../include/limits.h \
../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
../../include/time.h ../../include/sys/resource.h \
../../include/asm/system.h blk.h
ramdisk.s ramdisk.o : ramdisk.c ../../include/string.h ../../include/linux/config.h \
../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h \
../../include/sys/dirent.h ../../include/limits.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h \
../../include/asm/system.h ../../include/asm/segment.h \
../../include/linux/mm.h ../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/asm/system.h ../../include/asm/segment.h \
../../include/asm/memory.h blk.h
#ifndef _BLK_H
#define _BLK_H
#define NR_BLK_DEV 7
#define NR_BLK_DEV 10
/*
* NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads
......@@ -29,6 +29,7 @@ struct request {
char * buffer;
struct task_struct * waiting;
struct buffer_head * bh;
struct buffer_head * bhtail;
struct request * next;
};
......@@ -88,6 +89,24 @@ extern int * blk_size[NR_BLK_DEV];
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif (MAJOR_NR == 8)
/* scsi disk */
#define DEVICE_NAME "scsidisk"
#define DEVICE_INTR do_sd
#define DEVICE_REQUEST do_sd_request
#define DEVICE_NR(device) (MINOR(device) >> 4)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif (MAJOR_NR == 9)
/* scsi tape */
#define DEVICE_NAME "scsitape"
#define DEVICE_INTR do_st
#define DEVICE_REQUEST do_st_request
#define DEVICE_NR(device) (MINOR(device))
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif
/* unknown blk device */
#error "unknown blk device"
......@@ -130,22 +149,45 @@ extern inline void unlock_buffer(struct buffer_head * bh)
wake_up(&bh->b_wait);
}
extern inline void end_request(int uptodate)
extern inline void next_buffer(int uptodate)
{
DEVICE_OFF(CURRENT->dev);
if (CURRENT->bh) {
CURRENT->bh->b_uptodate = uptodate;
unlock_buffer(CURRENT->bh);
}
struct buffer_head *tmp;
CURRENT->bh->b_uptodate = uptodate;
unlock_buffer(CURRENT->bh);
if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r");
printk("dev %04x, block %d\n\r",CURRENT->dev,
CURRENT->bh->b_blocknr);
}
wake_up(&CURRENT->waiting);
tmp = CURRENT->bh;
CURRENT->bh = CURRENT->bh->b_reqnext;
tmp->b_reqnext = NULL;
if (!CURRENT->bh)
panic("next_buffer: request buffer list destroyed\r\n");
CURRENT->buffer = CURRENT->bh->b_data;
CURRENT->errors = 0;
}
extern inline void end_request(int uptodate)
{
struct request * tmp;
tmp = CURRENT;
DEVICE_OFF(tmp->dev);
CURRENT = tmp->next;
if (tmp->bh) {
tmp->bh->b_uptodate = uptodate;
unlock_buffer(tmp->bh);
}
if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r");
printk("dev %04x, block %d\n\r",tmp->dev,
tmp->bh->b_blocknr);
}
wake_up(&tmp->waiting);
tmp->dev = -1;
wake_up(&wait_for_request);
CURRENT->dev = -1;
CURRENT = CURRENT->next;
}
#ifdef DEVICE_INTR
......
This diff is collapsed.
This diff is collapsed.
......@@ -36,7 +36,10 @@ struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
{ NULL, NULL }, /* dev hd */
{ NULL, NULL }, /* dev ttyx */
{ NULL, NULL }, /* dev tty */
{ NULL, NULL } /* dev lp */
{ NULL, NULL }, /* dev lp */
{ NULL, NULL }, /* dev pipes */
{ NULL, NULL }, /* dev sd */
{ NULL, NULL } /* dev st */
};
/*
......@@ -128,6 +131,23 @@ static void make_request(int major,int rw, struct buffer_head * bh)
return;
}
repeat:
cli();
if (major == 3 && (req = blk_dev[major].current_request)) {
while (req = req->next) {
if (req->dev == bh->b_dev &&
!req->waiting &&
req->cmd == rw &&
req->sector + req->nr_sectors == bh->b_blocknr << 1 &&
req->nr_sectors < 254) {
req->bhtail->b_reqnext = bh;
req->bhtail = bh;
req->nr_sectors += 2;
bh->b_dirt = 0;
sti();
return;
}
}
}
/* we don't allow the write-requests to fill up the queue completely:
* we want some room for reads: they take precedence. The last third
* of the requests are only for reads.
......@@ -135,9 +155,8 @@ static void make_request(int major,int rw, struct buffer_head * bh)
if (rw == READ)
req = request+NR_REQUEST;
else
req = request+((NR_REQUEST*2)/3);
req = request+(NR_REQUEST/2);
/* find an empty request */
cli();
while (--req >= request)
if (req->dev < 0)
goto found;
......@@ -161,6 +180,7 @@ found: sti();
req->buffer = bh->b_data;
req->waiting = NULL;
req->bh = bh;
req->bhtail = bh;
req->next = NULL;
add_request(major+blk_dev,req);
}
......@@ -206,6 +226,8 @@ void ll_rw_block(int rw, struct buffer_head * bh)
{
unsigned int major;
if (!bh)
return;
if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
!(blk_dev[major].request_fn)) {
printk("ll_rw_block: Trying to read nonexistent block-device\n\r");
......
......@@ -4,7 +4,7 @@
* Written by Theodore Ts'o, 12/2/91
*/
#include <string.h>
#include <linux/string.h>
#include <linux/config.h>
#include <linux/sched.h>
......@@ -47,6 +47,17 @@ void do_rd_request(void)
goto repeat;
}
static struct file_operations rd_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
block_write, /* write - general block-dev write */
NULL, /* readdir - bad */
NULL, /* select */
NULL, /* ioctl */
NULL, /* no special open code */
NULL /* no special release code */
};
/*
* Returns amount of memory which needs to be reserved.
*/
......@@ -56,6 +67,7 @@ long rd_init(long mem_start, int length)
char *cp;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blkdev_fops[MAJOR_NR] = &rd_fops;
rd_start = (char *) mem_start;
rd_length = length;
cp = rd_start;
......
This diff is collapsed.
This diff is collapsed.
#ifndef _AHA1542_H
/* $Id: aha1542.h,v 1.1 1992/04/24 18:01:50 root Exp root $
*
* Header file for the adaptec 1542 driver for Linux
*
* $Log: aha1542.h,v $
* Revision 1.1 1992/04/24 18:01:50 root
* Initial revision
*
* Revision 1.1 1992/04/02 03:23:13 drew
* Initial revision
*
* Revision 1.3 1992/01/27 14:46:29 tthorn
* *** empty log message ***
*
*/
typedef unsigned char unchar;
/* I/O Port interface 4.2 */
/* READ */
#define STATUS base
#define STST 0x80 /* Self Test in Progress */
#define DIAGF 0x40 /* Internal Diagonostic Failure */
#define INIT 0x20 /* Mailbox Initialization Required */
#define IDLE 0x10 /* SCSI Host Adapter Idle */
#define CDF 0x08 /* Command/Data Out Port Full */
#define DF 0x04 /* Data In Port Full */
#define INVDCMD 0x01 /* Invalid H A Command */
#define STATMASK 0xfd /* 0x02 is reserved */
#define INTRFLAGS STATUS+2
#define ANYINTR 0x80 /* Any Interrupt */
#define SCRD 0x08 /* SCSI Reset Detected */
#define HACC 0x04 /* HA Command Complete */
#define MBOA 0x02 /* MBO Empty */
#define MBIF 0x01 /* MBI Full */
#define INTRMASK 0x8f
/* WRITE */
#define CONTROL STATUS
#define HRST 0x80 /* Hard Reset */
#define SRST 0x40 /* Soft Reset */
#define IRST 0x20 /* Interrupt Reset */
#define SCRST 0x10 /* SCSI Bus Reset */
/* READ/WRITE */
#define DATA STATUS+1
#define CMD_NOP 0x00 /* No Operation */
#define CMD_MBINIT 0x01 /* Mailbox Initialization */
#define CMD_START_SCSI 0x02 /* Start SCSI Command */
#define CMD_INQUIRY 0x04 /* Adapter Inquiry */
#define CMD_EMBOI 0x05 /* Enable MailBox Out Interrupt */
#define CMD_BUSON_TIME 0x07 /* Set Bus-On Time */
#define CMD_BUSOFF_TIME 0x08 /* Set Bus-Off Time */
#define CMD_RETDEVS 0x0a /* Return Installed Devices */
#define CMD_RETCONF 0x0b /* Return Configuration Data */
#define CMD_RETSETUP 0x0d /* Return Setup Data */
#define CMD_ECHO 0x1f /* ECHO Command Data */
/* Mailbox Definition 5.2.1 and 5.2.2 */
struct mailbox {
unchar status; /* Command/Status */
unchar ccbptr[3]; /* msb, .., lsb */
};
/* These belong in scsi.h also */
#define any2scsi(up, p) \
(up)[0] = (((long)(p)) >> 16) & 0xff; \
(up)[1] = ((long)(p)) >> 8; \
(up)[2] = ((long)(p));
#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
#define xany2scsi(up, p) \
(up)[0] = ((long)(p)) >> 24; \
(up)[1] = ((long)(p)) >> 16; \
(up)[2] = ((long)(p)) >> 8; \
(up)[3] = ((long)(p));
#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
+ (((long)(up)[2]) << 8) + ((long)(up)[3]) )
#define MAX_CDB 12
#define MAX_SENSE 14
struct ccb { /* Command Control Block 5.3 */
unchar op; /* Command Control Block Operation Code */
unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */
/* Outbound data transfer, length is checked*/
/* Inbound data transfer, length is checked */
/* Logical Unit Number */
unchar cdblen; /* SCSI Command Length */
unchar rsalen; /* Request Sense Allocation Length/Disable */
unchar datalen[3]; /* Data Length (msb, .., lsb) */
unchar dataptr[3]; /* Data Pointer */
unchar linkptr[3]; /* Link Pointer */
unchar commlinkid; /* Command Linking Identifier */
unchar hastat; /* Host Adapter Status (HASTAT) */
unchar tarstat; /* Target Device Status */
unchar reserved[2];
unchar cdb[MAX_CDB+MAX_SENSE];/* SCSI Command Descriptor Block */
/* REQUEST SENSE */
};
int aha1542_detect(int);
int aha1542_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
/*int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int));*/
int aha1542_abort(int);
char *aha1542_info(void);
int aha1542_reset(void);
#ifndef NULL
#define NULL 0
#endif
#define AHA1542 {"Adaptec 1542", aha1542_detect, \
aha1542_info, aha1542_command, \
/*aha1542_queuecommand*/ NULL, \
aha1542_abort, \
aha1542_reset, \
0, 7, 0}
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment