Commit 5b726c10 authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.99.7A (March 21, 1993)

More net-1 work. It's endless.

XT harddisk support by Pat Mackinlay.

sys_fsync() and SysV IPC code sys_ipc() stubs appear.

[original announcement below]

I don't generally announce ALPHA-diffs to quite this large an audience,
but I'll be partying^H^H^H^H^H^H^H^Hunavailable for the rest of the
week, and it's unlikely that I will be able to check mails or the
newsgroups until the start of April.  As a result, I'm putting up my
latest kernel version for ftp as it fixes some things in 0.99.7.

The ALPHA-diffs can be found on nic.funet.fi: in the directory
pub/OS/Linux/PEOPLE/Linus.  If you dislike patching, you can get the
full sources in "linux-0.99.7A.tar.z", or just get the diff file
"ALPHA-diff.z".

Changes in this release:
- the new kernel now detects the lock-up condition at startup if you
  have a faulty 386/387 coupling, and will use software floating point
  in that case.
- the Xia filesystem is updated to the latest version
- the DOS filesystem is updated to the latest version
- the XT disk driver is included: I haven't been able to test it, but
  at least it won't bother anybody if you don't configure it in..
- the latest serial diffs are in
- minor ultrastor fixes
- some changes to the keyboard and line printer drivers: I hope the
  keyboard lockups that some people have reported would be gone with
  this release.
- some fixes to arp.c

I'll be interested in success/failure reports, although I won't be able
to answer them for some time (and I might miss some of the posts on
c.o.l).

            Linus
parent f65d0bc9
......@@ -24,11 +24,11 @@ endif
#
# 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'.
# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
# the default of FLOPPY is used by 'build'.
#
ROOT_DEV = /dev/hdb1
ROOT_DEV = CURRENT
#
# uncomment the correct keyboard:
......@@ -45,20 +45,20 @@ ROOT_DEV = /dev/hdb1
# 0x10 - dieresis (umlaut)
KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
# KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_US -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_FR -DKBDFLAGS=0
# KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_UK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_DK_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_DVORAK -DKBDFLAGS=0
# KEYBOARD = -DKBD_SG -DKBDFLAGS=0
# KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_SF -DKBDFLAGS=0
# KEYBOARD = -DKBD_SF_LATIN1 -DKBDFLAGS=0x9F
# KEYBOARD = -DKBD_SF_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_NO -DKBDFLAGS=0
#
......@@ -139,7 +139,7 @@ tools/./version.h: tools/version.h
tools/version.h: $(CONFIGURE) Makefile
@./makever.sh
@echo \#define UTS_RELEASE \"0.99.pl7-`cat .version`\" > tools/version.h
@echo \#define UTS_RELEASE \"0.99.pl7A-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
......@@ -232,9 +232,9 @@ clean:
mrproper: clean
rm -f include/linux/autoconf.h tools/version.h
rm -f .version .config*
rm -f `find . -name .depend -print`
rm -f .depend `find . -name .depend -print`
backup: clean
backup: mrproper
cd .. && tar cf - linux | gzip -9 > backup.z
sync
......
......@@ -4,6 +4,8 @@ Kernel math emulation
CONFIG_MATH_EMULATION y/n n
Normal harddisk support
CONFIG_BLK_DEV_HD y/n y
XT harddisk support
CONFIG_BLK_DEV_XD y/n n
TCP/IP
CONFIG_TCPIP y/n y
Kernel profiling support
......
......@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/errno.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -102,6 +103,11 @@ int sys_sync(void)
return 0;
}
int sys_fsync(int fd)
{
return -ENOSYS;
}
void invalidate_buffers(dev_t dev)
{
int i;
......@@ -358,7 +364,7 @@ struct buffer_head * getblk(dev_t dev, int block, int size)
if (bh->b_count || bh->b_size != size)
goto repeat;
if (bh->b_dirt) {
sync_buffers(bh->b_dev);
sync_buffers(0);
goto repeat;
}
/* NOTE!! While we slept waiting for this block, somebody else might */
......
......@@ -460,7 +460,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
}
i = inode->i_mode;
if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current->
euid) || ((i & S_ISGID) && inode->i_gid != current->egid)) &&
euid) || ((i & S_ISGID) && !in_group_p(inode->i_gid))) &&
!suser()) {
retval = -EPERM;
goto exec_error2;
......
......@@ -48,7 +48,6 @@ static int ext_follow_link(struct inode * dir, struct inode * inode,
int flag, int mode, struct inode ** res_inode)
{
int error;
unsigned short fs;
struct buffer_head * bh;
*res_inode = NULL;
......
......@@ -376,6 +376,7 @@ static int empty_dir(struct inode * inode)
return 1;
info = &inode->i_sb->u.minix_sb;
block = 0;
bh = NULL;
offset = 2*info->s_dirsize;
if (inode->i_size & (info->s_dirsize-1))
goto bad_dir;
......
/*
* linux/fs/msdos/dir.c
*
* Written 1992 by Werner Almesberger
* Written 1992,1993 by Werner Almesberger
*
* MS-DOS directory handling functions
*/
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/stat.h>
static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
{
return -EISDIR;
......@@ -22,6 +22,7 @@ static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,in
static int msdos_readdir(struct inode *inode,struct file *filp,
struct dirent *dirent,int count);
static struct file_operations msdos_dir_operations = {
NULL, /* lseek - default */
msdos_dir_read, /* read */
......@@ -78,8 +79,7 @@ static int msdos_readdir(struct inode *inode,struct file *filp,
if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
bh = NULL;
while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
if (de->name[0] && ((unsigned char *) (de->name))[0] !=
DELETED_FLAG && !(de->attr & ATTR_VOLUME)) {
if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
for (i = last = 0; i < 8; i++) {
if (!(c = de->name[i])) break;
if (c >= 'A' && c <= 'Z') c += 32;
......
/*
* linux/fs/msdos/fat.c
*
* Written 1992 by Werner Almesberger
* Written 1992,1993 by Werner Almesberger
*/
#include <linux/msdos_fs.h>
......@@ -22,6 +22,7 @@ int fat_access(struct super_block *sb,int this,int new_value)
void *data,*data2,*c_data,*c_data2;
int first,last,next,copy;
if ((unsigned) (this-2) >= MSDOS_SB(sb)->clusters) return 0;
if (MSDOS_SB(sb)->fat_bits == 16) first = last = this*2;
else {
first = this*3/2;
......@@ -46,9 +47,9 @@ int fat_access(struct super_block *sb,int this,int new_value)
}
if (MSDOS_SB(sb)->fat_bits == 16) {
p_first = p_last = NULL; /* GCC needs that stuff */
next = ((unsigned short *) data)[(first & (SECTOR_SIZE-1))
>> 1];
if (next >= 0xfff8) next = -1;
next = CF_LE_W(((unsigned short *) data)[(first &
(SECTOR_SIZE-1)) >> 1]);
if (next >= 0xfff7) next = -1;
}
else {
p_first = &((unsigned char *) data)[first & (SECTOR_SIZE-1)];
......@@ -56,12 +57,12 @@ int fat_access(struct super_block *sb,int this,int new_value)
(SECTOR_SIZE-1)];
if (this & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
else next = (*p_first+(*p_last << 8)) & 0xfff;
if (next >= 0xff8) next = -1;
if (next >= 0xff7) next = -1;
}
if (new_value != -1) {
if (MSDOS_SB(sb)->fat_bits == 16)
((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >>
1] = new_value;
1] = CT_LE_W(new_value);
else {
if (this & 1) {
*p_first = (*p_first & 0xf) | (new_value << 4);
......@@ -167,8 +168,11 @@ printk("cache add: <%d,%d> %d (%d)\n",inode->i_dev,inode->i_ino,f_clu,d_clu);
for (walk = fat_cache; walk->next; walk = (last = walk)->next)
if (inode->i_dev == walk->device && walk->ino == inode->i_ino &&
walk->file_cluster == f_clu) {
if (walk->disk_cluster != d_clu)
panic("FAT cache corruption");
if (walk->disk_cluster != d_clu) {
printk("FAT cache corruption");
cache_inval_inode(inode);
return;
}
/* update LRU */
if (last == NULL) return;
last->next = walk->next;
......@@ -226,10 +230,7 @@ int get_cluster(struct inode *inode,int cluster)
if ((this = fat_access(inode->i_sb,this,-1)) == -1) return 0;
if (!this) return 0;
}
if (!(MSDOS_I(inode)->i_busy && inode->i_nlink))
cache_add(inode,cluster,this);
/* don't add clusters of moved files, because we can't invalidate them
when this inode is returned. */
cache_add(inode,cluster,this);
return this;
}
......@@ -278,8 +279,10 @@ int fat_free(struct inode *inode,int skip)
}
lock_fat(inode->i_sb);
while (this != -1) {
if (!(this = fat_access(inode->i_sb,this,0)))
panic("fat_free: deleting beyond EOF");
if (!(this = fat_access(inode->i_sb,this,0))) {
fs_panic(inode->i_sb,"fat_free: deleting beyond EOF");
break;
}
if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
MSDOS_SB(inode->i_sb)->free_clusters++;
inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
......
/*
* linux/fs/msdos/file.c
*
* Written 1992 by Werner Almesberger
* Written 1992,1993 by Werner Almesberger
*
* MS-DOS regular file handling primitives
*/
......
This diff is collapsed.
This diff is collapsed.
/*
* linux/fs/msdos/namei.c
*
* Written 1992 by Werner Almesberger
* Written 1992,1993 by Werner Almesberger
*/
#include <asm/segment.h>
......@@ -25,35 +25,33 @@ static char *reserved_names[] = {
/* Characters that are undesirable in an MS-DOS file name */
static char bad_chars[] = "*?<>|\"";
static char bad_if_strict[] = "+=,;";
static char bad_if_strict[] = "+=,; ";
/* Formats an MS-DOS file name. Rejects invalid names. */
static int msdos_format_name(char conv,const char *name,int len,char *res)
static int msdos_format_name(char conv,const char *name,int len,char *res,
int dot_dirs)
{
char *walk,**reserved;
char c;
int space;
if (*(unsigned char *)name == DELETED_FLAG) return -EINVAL;
if (name[0] == '.' && (len == 1 || (len == 2 &&
name[1] == '.'))) {
if (IS_FREE(name)) return -EINVAL;
if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
if (!dot_dirs) return -EEXIST;
memset(res+1,' ',10);
while (len--) *res++ = '.';
return 0;
}
space = 0; /* to make GCC happy */
space = 1; /* disallow names starting with a dot */
c = 0;
for (walk = res; len && walk-res < 8; walk++) {
c = *(name++);
c = *name++;
len--;
if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
if (c >= 'A' && c <= 'Z') {
if (conv == 's') return -EINVAL;
c += 32;
}
if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
if (c == '.') break;
space = c == ' ';
......@@ -61,26 +59,22 @@ static int msdos_format_name(char conv,const char *name,int len,char *res)
}
if (space) return -EINVAL;
if (conv == 's' && len && c != '.') {
c = *(name++);
c = *name++;
len--;
if (c != '.') return -EINVAL;
}
while (c != '.' && len--) c = *(name++);
if (walk == res) return -EINVAL;
while (c != '.' && len--) c = *name++;
if (c == '.') {
while (walk-res < 8) *walk++ = ' ';
while (len > 0 && walk-res < MSDOS_NAME) {
c = *(name++);
c = *name++;
len--;
if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
if (conv == 's' && strchr(bad_if_strict,c))
return -EINVAL;
if (c < ' ' || c == ':' || c == '\\' || c == '.')
return -EINVAL;
if (c >= 'A' && c <= 'Z') {
if (conv == 's') return -EINVAL;
c += 32;
}
if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
space = c == ' ';
*walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
}
......@@ -103,7 +97,7 @@ static int msdos_find(struct inode *dir,const char *name,int len,
int res;
if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
msdos_name)) < 0) return res;
msdos_name,1)) < 0) return res;
return msdos_scan(dir,msdos_name,bh,de,ino);
}
......@@ -126,8 +120,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
*result = dir;
return 0;
}
if (len == 2 && name[0] == '.' && name[1] == '.')
{
if (len == 2 && name[0] == '.' && name[1] == '.') {
ino = msdos_parent_ino(dir,0);
iput(dir);
if (ino < 0) return ino;
......@@ -152,8 +145,11 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
while (MSDOS_I(*result)->i_old) {
next = MSDOS_I(*result)->i_old;
iput(*result);
if (!(*result = iget(next->i_sb,next->i_ino)))
panic("msdos_lookup: Can't happen");
if (!(*result = iget(next->i_sb,next->i_ino))) {
fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
iput(dir);
return -ENOENT;
}
}
iput(dir);
return 0;
......@@ -170,6 +166,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
int res,ino;
if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) {
if (res != -ENOENT) return res;
if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
if ((res = msdos_add_cluster(dir)) < 0) return res;
if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res;
......@@ -201,7 +198,7 @@ int msdos_create(struct inode *dir,const char *name,int len,int mode,
if (!dir) return -ENOENT;
if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
msdos_name)) < 0) {
msdos_name,0)) < 0) {
iput(dir);
return res;
}
......@@ -226,7 +223,7 @@ static void dump_fat(struct super_block *sb,int start)
printk("[");
while (start) {
printk("%d ",start);
start = fat_access(sb,start,-1);
start = fat_access(sb,start,-1);
if (!start) {
printk("ERROR");
break;
......@@ -248,7 +245,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
int ino,res;
if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
msdos_name)) < 0) {
msdos_name,0)) < 0) {
iput(dir);
return res;
}
......@@ -289,7 +286,8 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
return 0;
mkdir_error:
iput(inode);
if (msdos_rmdir(dir,name,len) < 0) panic("rmdir in mkdir failed");
if (msdos_rmdir(dir,name,len) < 0)
fs_panic(dir->i_sb,"rmdir in mkdir failed");
unlock_creation();
return res;
}
......@@ -304,9 +302,9 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
bh = NULL;
inode = NULL;
res = -EINVAL;
if (name[0] == '.' && (len == 1 || (len == 2 &&
name[1] == '.'))) goto rmdir_done;
res = -EPERM;
if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
goto rmdir_done;
if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
res = -ENOENT;
if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;
......@@ -320,8 +318,7 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
pos = 0;
dbh = NULL;
while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1)
if (dde->name[0] && ((unsigned char *) dde->name)[0] !=
DELETED_FLAG && strncmp(dde->name,MSDOS_DOT,
if (!IS_FREE(dde->name) && strncmp(dde->name,MSDOS_DOT,
MSDOS_NAME) && strncmp(dde->name,MSDOS_DOTDOT,
MSDOS_NAME)) goto rmdir_done;
if (dbh) brelse(dbh);
......@@ -439,10 +436,13 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
}
iput(walk);
if ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) < 0)
return error;
exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)
>= 0;
while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) <
0) {
if (error != -ENOENT) return error;
error = msdos_add_cluster(new_dir);
if (error) return error;
}
exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0;
if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
brelse(free_bh);
if (exists) brelse(new_bh);
......@@ -536,9 +536,9 @@ int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
int old_ino,error;
if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
old_name,old_len,old_msdos_name)) < 0) goto rename_done;
old_name,old_len,old_msdos_name,1)) < 0) goto rename_done;
if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
new_name,new_len,new_msdos_name)) < 0) goto rename_done;
new_name,new_len,new_msdos_name,0)) < 0) goto rename_done;
if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
&old_ino)) < 0) goto rename_done;
lock_creation();
......
......@@ -330,7 +330,8 @@ struct inode * xiafs_new_inode(struct inode * dir)
inode->i_ino = tmp;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL;
inode->i_blocks = inode->i_blksize = 0;
inode->i_blocks = 0;
inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
return inode;
}
......
......@@ -101,8 +101,10 @@ static int xiafs_readdir(struct inode * inode,
put_fs_long(de->d_ino,&dirent->d_ino);
put_fs_word(i,&dirent->d_reclen);
brelse(bh);
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
if (!IS_RDONLY (inode)) {
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
return i;
}
de = (struct xiafs_direct *) (offset + bh->b_data);
......@@ -113,9 +115,9 @@ static int xiafs_readdir(struct inode * inode,
return 0;
}
}
inode->i_atime=CURRENT_TIME;
if (!IS_RDONLY (inode)) {
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
return 0;
}
......@@ -175,9 +175,10 @@ xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
if (!read)
return -EIO;
filp->f_reada = 1;
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
if (!IS_RDONLY (inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
return read;
}
......@@ -239,7 +240,7 @@ xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count
bh->b_dirt = 1;
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
filp->f_pos = pos;
inode->i_dirt = 1;
......
......@@ -176,8 +176,10 @@ int xiafs_bmap(struct inode * inode,int zone)
printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
return 0;
}
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
if (!IS_RDONLY (inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
if (zone < 8)
return inode->u.xiafs_i.i_zone[zone];
zone -= 8;
......@@ -236,6 +238,7 @@ dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr)
goto repeat;
}
*lp = tmp;
inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
return result;
}
......@@ -279,17 +282,18 @@ indt_getblk(struct inode * inode, struct buffer_head * bh,
}
result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
if (*lp) {
xiafs_free_zone(inode->i_sb,tmp);
xiafs_free_zone(inode->i_sb, tmp);
brelse(result);
goto repeat;
}
*lp = tmp;
inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
bh->b_dirt = 1;
brelse(bh);
return result;
}
struct buffer_head * xiafs_getblk(struct inode * inode, int zone, int create)
struct buffer_head * xiafs_getblk(struct inode * inode, int zone, int create)
{
struct buffer_head * bh;
u_long prev_addr=0;
......@@ -368,15 +372,16 @@ void xiafs_read_inode(struct inode * inode)
inode->i_mtime = raw_inode->i_mtime;
inode->i_atime = raw_inode->i_atime;
inode->i_ctime = raw_inode->i_ctime;
inode->i_blocks = 0;
inode->i_blksize = 0; /* let vfs estimate */
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
inode->i_blocks=0;
inode->i_rdev = raw_inode->i_zone[0];
else {
} else {
XIAFS_GET_BLOCKS(raw_inode, inode->i_blocks);
for (zone = 0; zone < 8; zone++)
inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[zone];
inode->u.xiafs_i.i_ind_zone = raw_inode->i_ind_zone;
inode->u.xiafs_i.i_dind_zone = raw_inode->i_dind_zone;
inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[zone] & 0xffffff;
inode->u.xiafs_i.i_ind_zone = raw_inode->i_ind_zone & 0xffffff;
inode->u.xiafs_i.i_dind_zone = raw_inode->i_dind_zone & 0xffffff;
}
brelse(bh);
if (S_ISREG(inode->i_mode))
......@@ -406,6 +411,12 @@ void xiafs_write_inode(struct inode * inode)
int zone;
ino_t ino;
if (IS_RDONLY (inode)) {
printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR);
inode->i_dirt = 0;
return;
}
ino = inode->i_ino;
if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
......@@ -427,20 +438,20 @@ void xiafs_write_inode(struct inode * inode)
raw_inode->i_gid = inode->i_gid;
raw_inode->i_nlinks = inode->i_nlink;
raw_inode->i_size = inode->i_size;
if (inode->i_ctime < inode->i_mtime)
inode->i_ctime=inode->i_mtime;
if (inode->i_atime < inode->i_ctime)
inode->i_atime=inode->i_ctime;
raw_inode->i_atime = inode->i_atime;
raw_inode->i_ctime = inode->i_ctime;
raw_inode->i_mtime = inode->i_mtime;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = inode->i_rdev;
else {
XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks);
for (zone = 0; zone < 8; zone++)
raw_inode->i_zone[zone] = inode->u.xiafs_i.i_zone[zone];
raw_inode->i_ind_zone = inode->u.xiafs_i.i_ind_zone;
raw_inode->i_dind_zone = inode->u.xiafs_i.i_dind_zone;
raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000)
| (inode->u.xiafs_i.i_zone[zone] & 0xffffff);
raw_inode->i_ind_zone = (raw_inode->i_ind_zone & 0xff000000)
| (inode->u.xiafs_i.i_ind_zone & 0xffffff);
raw_inode->i_dind_zone = (raw_inode->i_dind_zone & 0xff000000)
| (inode->u.xiafs_i.i_dind_zone & 0xffffff);
}
inode->i_dirt=0;
bh->b_dirt=1;
......
......@@ -212,7 +212,7 @@ static struct buffer_head * xiafs_add_entry(struct inode * dir,
}
}
if (!de->d_ino && RNDUP4(namelen)+8 <= de->d_rec_len) {
dir->i_mtime = CURRENT_TIME;
dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
memcpy(de->d_name, name, namelen);
de->d_name[namelen]=0;
......@@ -316,7 +316,7 @@ int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev
}
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = rdev;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
bh = xiafs_add_entry(dir, name, len, &de, NULL);
if (!bh) {
......@@ -357,7 +357,7 @@ int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
}
inode->i_op = &xiafs_dir_inode_operations;
inode->i_size = XIAFS_ZSIZE(dir->i_sb);
inode->i_mtime = inode->i_atime = CURRENT_TIME;
inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
dir_block = xiafs_bread(inode,0,1);
if (!dir_block) {
iput(dir);
......@@ -524,7 +524,7 @@ int xiafs_rmdir(struct inode * dir, const char * name, int len)
inode->i_nlink=0;
inode->i_dirt=1;
dir->i_nlink--;
dir->i_mtime = CURRENT_TIME;
dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt=1;
retval = 0;
end_rmdir:
......@@ -569,10 +569,9 @@ int xiafs_unlink(struct inode * dir, const char * name, int len)
}
xiafs_rm_entry(de, de_pre);
bh->b_dirt = 1;
dir->i_mtime = CURRENT_TIME;
dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
inode->i_nlink--;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
retval = 0;
end_unlink:
......@@ -668,7 +667,7 @@ int xiafs_link(struct inode * oldinode, struct inode * dir,
brelse(bh);
iput(dir);
oldinode->i_nlink++;
oldinode->i_ctime = CURRENT_TIME;
oldinode->i_atime = oldinode->i_ctime = CURRENT_TIME;
oldinode->i_dirt = 1;
iput(oldinode);
return 0;
......
......@@ -57,8 +57,10 @@ static int xiafs_readlink(struct inode * inode, char * buffer, int buflen)
if (buflen > BLOCK_SIZE)
buflen = BLOCK_SIZE;
bh = xiafs_bread(inode, 0, 0);
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
if (!IS_RDONLY (inode)) {
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
iput(inode);
if (!bh)
return 0;
......@@ -90,8 +92,10 @@ static int xiafs_follow_link(struct inode * dir, struct inode * inode,
*res_inode = inode;
return 0;
}
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
if (!IS_RDONLY (inode)) {
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
if (current->link_count > 5) {
iput(inode);
iput(dir);
......
......@@ -60,6 +60,7 @@ static int trunc_direct(struct inode * inode)
else {
*lp = 0;
inode->i_dirt = 1;
inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp);
}
brelse(bh);
......@@ -105,6 +106,7 @@ static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
else {
*indp = 0;
ind_bh->b_dirt = 1;
inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp);
}
brelse(bh);
......@@ -117,6 +119,7 @@ static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
else {
tmp = *lp;
*lp = 0;
inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp);
}
}
......@@ -166,6 +169,7 @@ static int trunc_dindirect(struct inode * inode)
tmp = *lp;
*lp = 0;
inode->i_dirt = 1;
inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp);
}
}
......@@ -189,7 +193,7 @@ void xiafs_truncate(struct inode * inode)
current->counter = 0;
schedule();
}
inode->i_mtime = CURRENT_TIME;
inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1;
}
......
......@@ -17,4 +17,16 @@ extern char internal_error_message[];
#define XIAFS_BITS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS + 3 + XIAFS_ZSHIFT(sp))
#define XIAFS_INODES_PER_Z(sp) (_XIAFS_INODES_PER_BLOCK << XIAFS_ZSHIFT(sp))
/* Use the most significant bytes of zone pointers to store block counter. */
/* This is ugly, but it works. Note, We have another 7 bytes for "expension". */
#define XIAFS_GET_BLOCKS(row_ip, blocks) \
blocks=((((row_ip)->i_zone[0] >> 24) & 0xff )|\
(((row_ip)->i_zone[1] >> 16) & 0xff00 )|\
(((row_ip)->i_zone[2] >> 8) & 0xff0000 ) )
/* XIAFS_PUT_BLOCKS should be called before saving zone pointers */
#define XIAFS_PUT_BLOCKS(row_ip, blocks) \
(row_ip)->i_zone[2]=((blocks)<< 8) & 0xff000000;\
(row_ip)->i_zone[1]=((blocks)<<16) & 0xff000000;\
(row_ip)->i_zone[0]=((blocks)<<24) & 0xff000000
......@@ -95,7 +95,6 @@ extern int copy_page_tables(struct task_struct * new);
extern int unmap_page_range(unsigned long from, unsigned long size);
extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, int mask);
extern int zeromap_page_range(unsigned long from, unsigned long size, int mask);
extern void write_verify(unsigned long address);
extern void do_wp_page(unsigned long error_code, unsigned long address,
struct task_struct *tsk, unsigned long user_esp);
......
......@@ -6,6 +6,8 @@
*/
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/fd.h>
#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */
#define SECTOR_SIZE 512 /* sector size (bytes) */
......@@ -32,6 +34,11 @@
/* attribute bits that are copied "as is" */
#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
#define IS_FREE(n) (!*(n) || *(unsigned char *) (n) == DELETED_FLAG || \
*(unsigned char *) (n) == FD_FILL_BYTE)
#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
/* valid file mode bits */
#define MSDOS_SB(s) (&((s)->u.msdos_sb))
#define MSDOS_I(i) (&((i)->u.msdos_i))
......@@ -40,10 +47,26 @@
#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
#define MSDOS_FAT12 4086 /* maximum number of clusters in a 12 bit FAT */
#define MSDOS_FAT12 4078 /* maximum number of clusters in a 12 bit FAT */
/*
* Conversion from and to little-endian byte order. (no-op on i386/i486)
*
* Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian, BE = big-
* endian, c: W = word (16 bits), L = longword (32 bits)
*/
#define CF_LE_W(v) (v)
#define CF_LE_L(v) (v)
#define CT_LE_W(v) (v)
#define CT_LE_L(v) (v)
struct msdos_boot_sector {
char ignored[13];
char ignored[3]; /* Boot strap short or near jump */
char system_id[8]; /* Name - can be used to special case
partition manager volumes */
unsigned char sector_size[2];/* bytes per logical sector */
unsigned char cluster_size; /* sectors/cluster */
unsigned short reserved; /* reserved sectors */
unsigned char fats; /* number of FATs */
......@@ -51,8 +74,8 @@ struct msdos_boot_sector {
unsigned char sectors[2]; /* number of sectors */
unsigned char media; /* media code (unused) */
unsigned short fat_length; /* sectors/FAT */
unsigned short secs_track; /* sectors per track (unused) */
unsigned short heads; /* number of heads (unused) */
unsigned short secs_track; /* sectors per track */
unsigned short heads; /* number of heads */
unsigned long hidden; /* hidden sectors (unused) */
unsigned long total_sect; /* number of sectors (if sectors == 0) */
};
......@@ -80,11 +103,11 @@ struct fat_cache {
/* Convert attribute bits and a mask to the UNIX mode. */
#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? 0444 : 0777))
#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? 0555 : 0777))
/* Convert the UNIX mode to MS-DOS attribute bits. */
#define MSDOS_MKATTR(m) (!(m & 0200) ? ATTR_RO : ATTR_NONE)
#define MSDOS_MKATTR(m) ((m & 0200) ? ATTR_NONE : ATTR_RO)
static inline struct buffer_head *msdos_sread(int dev,int sector,void **start)
......@@ -100,6 +123,7 @@ static inline struct buffer_head *msdos_sread(int dev,int sector,void **start)
/* misc.c */
extern void fs_panic(struct super_block *s,char *msg);
extern int is_binary(char conversion,char *extension);
extern void lock_creation(void);
extern void unlock_creation(void);
......@@ -149,6 +173,7 @@ extern void msdos_statfs(struct super_block *sb,struct statfs *buf);
extern int msdos_bmap(struct inode *inode,int block);
extern void msdos_read_inode(struct inode *inode);
extern void msdos_write_inode(struct inode *inode);
extern int msdos_notify_change(int flags,struct inode *inode);
/* dir.c */
......
......@@ -2,8 +2,9 @@
#define _MSDOS_FS_I
/*
* msdos file system inode data in memory
* MS-DOS file system inode data in memory
*/
struct msdos_inode_info {
int i_start; /* first cluster or 0 */
int i_attrs; /* unused attribute bits */
......
#ifndef _MSDOS_FS_SB
#define _MSDOS_FS_SB
/*
* MS-DOS file system in-core superblock data
*/
struct msdos_sb_info {
unsigned short cluster_size; /* sectors/cluster */
unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
......@@ -15,6 +19,7 @@ struct msdos_sb_info {
unsigned char conversion; /* b = binary, t = text, a = auto */
struct wait_queue *fat_wait;
int fat_lock;
int prev_free; /* previously returned free cluster number */
int free_clusters; /* -1 if undefined */
};
......
......@@ -143,16 +143,16 @@ struct tss_struct {
struct task_struct {
/* these are hardcoded - don't touch */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
long signal;
unsigned long signal;
unsigned long blocked; /* bitmap of masked signals */
unsigned long flags; /* per process flags, defined below */
/* various fields */
struct sigaction sigaction[32];
long blocked; /* bitmap of masked signals */
unsigned long saved_kernel_stack;
unsigned long kernel_stack_page;
unsigned int flags; /* per process flags, defined below */
/* various fields */
int exit_code;
int dumpable:1;
int swappable:1;
......@@ -220,9 +220,9 @@ struct task_struct {
* your own risk!. Base=0, limit=0x1fffff (=2MB)
*/
#define INIT_TASK \
/* state etc */ { 0,15,15, \
/* signals */ 0,{{ 0, },},0,0,0, \
/* flags */ 0, \
/* state etc */ { 0,15,15,0,0,0, \
/* signals */ {{ 0, },}, \
/* stack */ 0,0, \
/* ec,brk... */ 0,0,0,0,0,0,0,0, \
/* argv.. */ 0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
......@@ -275,7 +275,7 @@ extern void interruptible_sleep_on(struct wait_queue ** p);
extern void wake_up(struct wait_queue ** p);
extern void wake_up_interruptible(struct wait_queue ** p);
extern int send_sig(long sig,struct task_struct * p,int priv);
extern int send_sig(unsigned long sig,struct task_struct * p,int priv);
extern int in_group_p(gid_t grp);
extern int request_irq(unsigned int irq,void (*handler)(int));
......
......@@ -119,6 +119,8 @@ extern int sys_vm86();
extern int sys_wait4();
extern int sys_swapoff();
extern int sys_sysinfo();
extern int sys_ipc();
extern int sys_fsync();
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,
......@@ -141,7 +143,7 @@ sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_setpriority,
sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_socketcall,
sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
sys_newfstat, sys_newuname, sys_iopl, sys_vhangup, sys_idle, sys_vm86,
sys_wait4, sys_swapoff, sys_sysinfo };
sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
......@@ -22,6 +22,8 @@
* SCSI_TIMER scsi.c timeout timer
*
* NET_TIMER tcp/ip timeout timer
*
* MISC_TIMER reserved for special uses like the 387 timeouts etc
*/
#define BLANK_TIMER 0
......@@ -33,6 +35,7 @@
#define SCSI_TIMER 18
#define NET_TIMER 19
#define SOUND_TIMER 20
#define MISC_TIMER 21
struct timer_struct {
unsigned long expires;
......
......@@ -99,6 +99,7 @@ struct serial_struct {
#define ASYNC_HUP_NOTIFY 0x0001 /* Notify blocked open on hangups */
#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
#define ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */
#define ASYNC_SKIP_TEST 0x0008 /* Skip UART test on bootup */
#define ASYNC_SPD_MASK 0x0030
#define ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
......
#ifndef _LINUX_XD_H
#define _LINUX_XD_H
/*
* This file contains the definitions for the IO ports and errors etc. for XT hard disk controllers (at least the DTC 5150X).
*
* Author: Pat Mackinlay, smackinla@cc.curtin.edu.au
* Date: 29/09/92
*
* Revised: 01/01/93, ...
*
* Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler, kevinf@agora.rain.com)
* Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and Wim Van Dorst.
*/
/* XT hard disk controller registers */
#define XD_DATA (xd_iobase + 0x00) /* data RW register */
#define XD_RESET (xd_iobase + 0x01) /* reset WO register */
#define XD_STATUS (xd_iobase + 0x01) /* status RO register */
#define XD_SELECT (xd_iobase + 0x02) /* select WO register */
#define XD_JUMPER (xd_iobase + 0x02) /* jumper RO register */
#define XD_CONTROL (xd_iobase + 0x03) /* DMAE/INTE WO register */
#define XD_RESERVED (xd_iobase + 0x03) /* reserved */
/* XT hard disk controller commands (incomplete list) */
#define CMD_TESTREADY 0x00 /* test drive ready */
#define CMD_RECALIBRATE 0x01 /* recalibrate drive */
#define CMD_SENSE 0x03 /* request sense */
#define CMD_FORMATDRV 0x04 /* format drive */
#define CMD_VERIFY 0x05 /* read verify */
#define CMD_FORMATTRK 0x06 /* format track */
#define CMD_FORMATBAD 0x07 /* format bad track */
#define CMD_READ 0x08 /* read */
#define CMD_WRITE 0x0A /* write */
#define CMD_SEEK 0x0B /* seek */
/* Controller specific commands */
#define CMD_DTCSETPARAM 0x0C /* set drive parameters (DTC 5150X only?) */
#define CMD_DTCGETECC 0x0D /* get ecc error length (DTC 5150X only?) */
#define CMD_DTCREADBUF 0x0E /* read sector buffer (DTC 5150X only?) */
#define CMD_DTCWRITEBUF 0x0F /* write sector buffer (DTC 5150X only?) */
#define CMD_DTCREMAPTRK 0x11 /* assign alternate track (DTC 5150X only?) */
#define CMD_DTCGETPARAM 0xFB /* get drive parameters (DTC 5150X only?) */
#define CMD_DTCSETSTEP 0xFC /* set step rate (DTC 5150X only?) */
#define CMD_DTCSETGEOM 0xFE /* set geometry data (DTC 5150X only?) */
#define CMD_DTCGETGEOM 0xFF /* get geometry data (DTC 5150X only?) */
#define CMD_ST11GETGEOM 0xF8 /* get geometry data (Seagate ST11R/M only?) */
#define CMD_WDSETPARAM 0x0C /* set drive parameters (WD 1004A27X only?) */
/* Bits for command status byte */
#define CSB_ERROR 0x02 /* error */
#define CSB_LUN 0x20 /* logical Unit Number */
/* XT hard disk controller status bits */
#define STAT_READY 0x01 /* controller is ready */
#define STAT_INPUT 0x02 /* data flowing from controller to host */
#define STAT_COMMAND 0x04 /* controller in command phase */
#define STAT_SELECT 0x08 /* controller is selected */
#define STAT_REQUEST 0x10 /* controller requesting data */
#define STAT_INTERRUPT 0x20 /* controller requesting interrupt */
/* XT hard disk controller control bits */
#define PIO_MODE 0x00 /* control bits to set for PIO */
#define DMA_MODE 0x03 /* control bits to set for DMA & interrupt */
#define XD_MAXDRIVES 2 /* maximum 2 drives */
#define XD_TIMEOUT 100 /* 1 second timeout */
#define XD_RETRIES 4 /* maximum 4 retries */
#undef DEBUG /* define for debugging output */
#undef XD_OVERRIDE /* define to override auto-detection */
#ifdef DEBUG
#define DEBUG_STARTUP /* debug driver initialisation */
#define DEBUG_OVERRIDE /* debug override geometry detection */
#define DEBUG_READWRITE /* debug each read/write command */
#define DEBUG_OTHER /* debug misc. interrupt/DMA stuff */
#define DEBUG_COMMAND /* debug each controller command */
#endif DEBUG
/* this structure defines the XT drives and their types */
typedef struct {
u_char heads;
u_short cylinders;
u_char sectors;
u_char control;
} XD_INFO;
#define HDIO_GETGEO 0x0301 /* get drive geometry */
/* this structure is returned to the HDIO_GETGEO ioctl */
typedef struct {
u_char heads;
u_char sectors;
u_short cylinders;
u_long start;
} XD_GEOMETRY;
/* this structure defines a ROM BIOS signature */
typedef struct {
u_long offset;
u_char *string;
void (*init_controller)(u_char *address);
void (*init_drive)(u_char drive);
u_char *name;
} XD_SIGNATURE;
extern void resetup_one_dev (struct gendisk *dev,unsigned int drive);
u_long xd_init(u_long mem_start,u_long mem_end);
static u_char xd_detect (u_char *controller,u_char **address);
static u_char xd_initdrives (void (*init_drive)(u_char drive));
static void xd_geninit (void);
static int xd_open (struct inode *inode,struct file *file);
static void do_xd_request (void);
static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned int arg);
static void xd_release (struct inode *inode,struct file *file);
static int xd_reread_partitions (int dev);
static int xd_readwrite (u_char operation,u_char drive,u_char *buffer,u_int block,u_int count);
static void xd_recalibrate (u_char drive);
static void xd_interrupt_handler (int unused);
static u_char xd_setup_dma (u_char opcode,u_char *buffer,u_int count);
static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control);
static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout);
static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout);
/* card specific setup and geometry gathering code */
#ifndef XD_OVERRIDE
static void xd_dtc5150x_init_controller (u_char *address);
static void xd_dtc5150x_init_drive (u_char drive);
static void xd_wd1004a27x_init_controller (u_char *address);
static void xd_wd1004a27x_init_drive (u_char drive);
static void xd_seagate11_init_controller (u_char *address);
static void xd_seagate11_init_drive (u_char drive);
static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc);
#endif XD_OVERRIDE
static void xd_override_init_controller (u_char *address);
static void xd_override_init_drive (u_char drive);
#endif _LINUX_XD_H
......@@ -18,6 +18,7 @@
#include <linux/head.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/timer.h>
extern unsigned long * prof_buffer;
extern unsigned long prof_len;
......@@ -203,6 +204,17 @@ static void parse_options(char *line)
envp_init[envs+1] = NULL;
}
static void copro_timeout(void)
{
#ifdef CONFIG_MATH_EMULATION
printk(" Trying to use software floating point\n");
hard_math = 0;
__asm__("movl %%cr0,%%eax ; xorl $6,%%eax ; movl %%eax,%%cr0":::"ax");
#else
printk(" No software floating point - tough cookies\n");
#endif
}
void start_kernel(void)
{
/*
......@@ -266,13 +278,19 @@ void start_kernel(void)
if (hard_math) {
unsigned short control_word;
printk("Checking for 387 error mechanism ...");
timer_table[MISC_TIMER].expires = jiffies+100;
timer_table[MISC_TIMER].fn = copro_timeout;
timer_active |= 1<<MISC_TIMER;
printk("You have a bad 386/387 coupling.");
__asm__("fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
control_word &= 0xffc0;
__asm__("fldcw %0 ; fwait"::"m" (*&control_word));
outb_p(inb_p(0x21) | (1 << 2), 0x21);
__asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait");
printk(" ok, using %s.\n",ignore_irq13?"exception 16":"irq13");
timer_active &= ~(1<<MISC_TIMER);
if (hard_math)
printk("\rMath coprocessor using %s error reporting.\n",
ignore_irq13?"exception 16":"irq13");
}
move_to_user_mode();
if (!fork()) /* we count on this going ok */
......
......@@ -18,7 +18,7 @@
SUBDIRS = scsi
OBJS = hd.o ll_rw_blk.o floppy.o ramdisk.o genhd.o
OBJS = xd.o hd.o ll_rw_blk.o floppy.o ramdisk.o genhd.o
all: blk_drv.a scsisubdirs
......@@ -38,6 +38,9 @@ dep:
$(CPP) -M *.c > .depend
for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep); done
xd.o:
$(CC) $(CFLAGS) -fno-omit-frame-pointer $(RAMDISK) -c $<
dummy:
#
......
......@@ -78,6 +78,8 @@ extern void rd_load(void);
extern long rd_init(long mem_start, int length);
extern int ramdisk_size;
extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end);
#define RO_IOCTLS(dev,where) \
case BLKROSET: if (!suser()) return -EPERM; \
set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
......@@ -147,6 +149,14 @@ extern int ramdisk_size;
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif (MAJOR_NR == 13)
/* xt hard disk */
#define DEVICE_NAME "xt disk"
#define DEVICE_REQUEST do_xd_request
#define DEVICE_NR(device) (MINOR(device) >> 6)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#else
/* unknown blk device */
#error "unknown blk device"
......
......@@ -385,6 +385,9 @@ long blk_dev_init(long mem_start, long mem_end)
memset(ro_bits,0,sizeof(ro_bits));
#ifdef CONFIG_BLK_DEV_HD
mem_start = hd_init(mem_start,mem_end);
#endif
#ifdef CONFIG_BLK_DEV_XD
mem_start = xd_init(mem_start,mem_end);
#endif
if (ramdisk_size)
mem_start += rd_init(mem_start, ramdisk_size*1024);
......
......@@ -91,8 +91,8 @@ struct config {
unsigned char interrupt: 4;
unsigned char dma_channel: 3;
unsigned char bios_drive_number: 1;
unsigned char heads: 6;
unsigned char sectors: 6;
unsigned char heads;
unsigned char sectors;
unsigned char ha_scsi_id: 3;
unsigned char subversion: 4;
};
......
This diff is collapsed.
......@@ -54,6 +54,7 @@
#define NPAR 16
extern void vt_init(void);
extern void register_console(void (*proc)(const char *));
unsigned long video_num_columns; /* Number of text columns */
unsigned long video_num_lines; /* Number of test lines */
......@@ -1244,6 +1245,7 @@ long con_init(long kmem_start)
long base;
int orig_x = ORIG_X;
int orig_y = ORIG_Y;
void console_print(const char * b);
vc_scrmembuf = (unsigned short *) kmem_start;
video_num_columns = ORIG_VIDEO_COLS;
......@@ -1334,6 +1336,7 @@ long con_init(long kmem_start)
display_desc,
video_num_columns,video_num_lines,
NR_CONSOLES);
register_console(console_print);
return kmem_start;
}
......
......@@ -40,6 +40,7 @@
extern void do_keyboard_interrupt(void);
extern void ctrl_alt_del(void);
extern void change_console(unsigned int new_console);
extern void fake_keyboard_interrupt(void);
unsigned long kbd_flags = 0;
unsigned long kbd_dead_keys = 0;
......@@ -75,23 +76,6 @@ static inline void kb_wait(void)
break;
}
/*
* send_cmd() sends a command byte to the keyboard.
*/
static inline void send_cmd(unsigned char c)
{
kb_wait();
outb(c,0x64);
}
static inline unsigned char get_scancode(void)
{
kb_wait();
if (inb_p(0x64) & 0x01)
return inb(0x60);
return 0;
}
static void keyboard_interrupt(int int_pt_regs)
{
static unsigned char rep = 0xff;
......@@ -102,8 +86,11 @@ static void keyboard_interrupt(int int_pt_regs)
if (!kbd_dead_keys)
kbd_prev_dead_keys = 0;
kbd_dead_keys = 0;
send_cmd(0xAD);
scancode = get_scancode();
kb_wait();
if (!(inb_p(0x64) & 0x01))
goto end_kbd_intr;
scancode = inb(0x60);
mark_bh(KEYBOARD_BH);
if (scancode == 0xfa) {
acknowledge = 1;
goto end_kbd_intr;
......@@ -145,8 +132,6 @@ static void keyboard_interrupt(int int_pt_regs)
key_table[scancode](scancode);
rep = scancode;
end_kbd_intr:
send_cmd(0xAE);
mark_bh(KEYBOARD_BH);
}
static void put_queue(int ch)
......@@ -1116,13 +1101,15 @@ unsigned int handle_diacr(unsigned int ch)
{
static unsigned char diacr_table[] =
{'`', 180, '^', '~', 168, 0}; /* Must end with 0 */
static unsigned char ret_diacr[] =
{'`', '\'', '^', '~', '"' }; /* Must not end with 0 */
int i;
for(i=0; diacr_table[i]; i++)
if (ch==diacr_table[i] && ((1<<i)&kbd->kbd_flags)) {
if (diacr == i) {
diacr=-1;
return ch; /* pressed twice */
return ret_diacr[i]; /* pressed twice */
} else {
diacr=i; /* key is dead */
return 0;
......@@ -1131,7 +1118,7 @@ unsigned int handle_diacr(unsigned int ch)
if (diacr == -1)
return ch;
else if (ch == ' ') {
ch=diacr_table[diacr];
ch=ret_diacr[diacr];
diacr=-1;
return ch;
} else if (ch<64 || ch>122) {
......@@ -1366,6 +1353,10 @@ static void kbd_bh(void * unused)
want_console = -1;
}
do_keyboard_interrupt();
cli();
if (inb_p(0x64) & 0x01)
fake_keyboard_interrupt();
sti();
}
long no_idt[2] = {0, 0};
......@@ -1475,6 +1466,6 @@ unsigned long kbd_init(unsigned long kmem_start)
}
bh_base[KEYBOARD_BH].routine = kbd_bh;
request_irq(KEYBOARD_IRQ,keyboard_interrupt);
keyboard_interrupt(0);
mark_bh(KEYBOARD_BH);
return kmem_start;
}
......@@ -299,6 +299,8 @@ static int lp_open(struct inode * inode, struct file * file)
sa.sa_restorer = NULL;
ret = irqaction(irq, &sa);
if (ret) {
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
printk("lp%d unable to use interrupt %d, error %d\n", irq, ret);
return ret;
}
......@@ -317,6 +319,7 @@ static void lp_release(struct inode * inode, struct file * file)
if ((irq = LP_IRQ(minor))) {
free_irq(irq);
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
}
LP_F(minor) &= ~LP_BUSY;
......@@ -353,28 +356,48 @@ static int lp_ioctl(struct inode *inode, struct file *file,
case LPSETIRQ: {
int ret;
int oldirq;
int newirq = arg;
struct lp_struct *lp = &lp_table[minor];
struct sigaction sa;
if (!suser())
return -EPERM;
if ((oldirq = LP_IRQ(minor))) {
oldirq = LP_IRQ(minor);
/* Allocate buffer now if we are going to need it */
if (!oldirq && newirq) {
if (!(lp->lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)))
return -ENOMEM;
}
if (oldirq) {
free_irq(oldirq);
}
if (arg) {
if (newirq) {
/* Install new irq */
sa.sa_handler = lp_interrupt;
sa.sa_flags = SA_INTERRUPT;
sa.sa_mask = 0;
sa.sa_restorer = NULL;
if ((ret = irqaction(arg, &sa))) {
if (oldirq)
if ((ret = irqaction(newirq, &sa))) {
if (oldirq) {
/* restore old irq */
irqaction(oldirq, &sa);
} else {
/* We don't need the buffer */
kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
lp->lp_buffer = NULL;
}
return ret;
}
}
LP_IRQ(minor) = arg;
if (oldirq && !newirq) {
/* We don't need the buffer */
kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
lp->lp_buffer = NULL;
}
LP_IRQ(minor) = newirq;
lp_reset(minor);
break;
}
......@@ -405,8 +428,10 @@ long lp_init(long kmem_start)
unsigned int testvalue = 0;
int count = 0;
if (register_chrdev(6,"lp",&lp_fops))
if (register_chrdev(6,"lp",&lp_fops)) {
printk("unable to get major 6 for line printer\n");
return kmem_start;
}
/* take on all known port values */
for (offset = 0; offset < LP_NO; offset++) {
/* write to port & read back to check */
......
This diff is collapsed.
......@@ -1060,6 +1060,7 @@ static void release_dev(int dev, struct file * filp)
{
struct tty_struct *tty, *o_tty;
struct termios *tp, *o_tp;
struct task_struct **p;
tty = tty_table[dev];
tp = tty_termios[dev];
......@@ -1107,6 +1108,15 @@ static void release_dev(int dev, struct file * filp)
if (tty->count)
return;
/*
* Make sure there aren't any processes that still think this
* tty is their controlling tty.
*/
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
if ((*p) && (*p)->tty == tty->line)
(*p)->tty = -1;
}
if (ldiscs[tty->disc].close != NULL)
ldiscs[tty->disc].close(tty);
......
......@@ -20,9 +20,9 @@
int sys_close(int fd);
int getrusage(struct task_struct *, int, struct rusage *);
int send_sig(long sig,struct task_struct * p,int priv)
int send_sig(unsigned long sig,struct task_struct * p,int priv)
{
if (!p || (sig < 0) || (sig > 32))
if (!p || sig > 32)
return -EINVAL;
if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
(current->euid != p->euid) && (current->uid != p->uid) && !suser())
......
......@@ -6,7 +6,7 @@
/*
* 'fork.c' contains the help-routines for the 'fork' system call
* (see also system_call.s), and some misc functions ('verify_area').
* (see also system_call.s).
* Fork is rather simple, once you get the hang of it, but the memory
* management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
*/
......@@ -24,27 +24,6 @@
long last_pid=0;
int verify_area(int type, void * addr, unsigned long size)
{
unsigned long start;
start = (unsigned long) addr;
if (start >= TASK_SIZE)
return -EFAULT;
if (size > TASK_SIZE - start)
return -EFAULT;
if (type == VERIFY_READ)
return 0;
size += start & 0xfff;
size >>= 12;
start &= 0xfffff000;
do {
write_verify(start);
start += 4096;
} while (size--);
return 0;
}
static int find_empty_process(void)
{
int i, task_nr;
......
......@@ -125,6 +125,11 @@ static void (*bad_interrupt[16])(void) = {
bad_IRQ14_interrupt, bad_IRQ15_interrupt
};
void fake_keyboard_interrupt(void)
{
IRQ1_interrupt();
}
/*
* Initial irq handlers.
*/
......
......@@ -2,6 +2,13 @@
* linux/kernel/printk.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Modified to make sys_syslog() more flexible: added commands to
* return the last 4k of kernel messages, regardless of whether
* they've been read or not. Added option to suppress kernel printk's
* to the console. Added hook for sending the console messages
* elsewhere, in preparation for a serial line console (someday).
* Ted Ts'o, 2/11/93.
*/
#include <stdarg.h>
......@@ -18,46 +25,48 @@ static char buf[1024];
extern int vsprintf(char * buf, const char * fmt, va_list args);
extern void console_print(const char *);
static unsigned long log_page = 0;
static void (*console_print_proc)(const char *) = 0;
static char log_buf[4096];
static unsigned long log_start = 0;
static unsigned long logged_chars = 0;
unsigned long log_size = 0;
int log_to_console = 1;
struct wait_queue * log_wait = NULL;
/*
* Commands to sys_syslog:
*
* 0 -- Close the log. Currently a NOP.
* 1 -- Open and reset log.
* 2 -- Read from the log.
* 3 -- Read up to the last 4k of messages in the ring buffer.
* 4 -- Read and clear last 4k of messages in the ring buffer
* 5 -- Clear ring buffer.
* 6 -- Disable printk's to console
* 7 -- Enable printk's to console
*/
int sys_syslog(int type, char * buf, int len)
{
unsigned long i;
unsigned long i, j, count;
int do_clear = 0;
char c;
if (!suser())
if ((type != 3) && !suser())
return -EPERM;
switch (type) {
case 0:
i = log_page;
log_page = 0;
free_page(i);
wake_up_interruptible(&log_wait);
case 0: /* Close log */
return 0;
case 1:
i = get_free_page(GFP_KERNEL);
if (log_page) {
free_page(i);
return 0;
} else if ((log_page = i) != 0) {
log_start = log_size = 0;
return 0;
}
return -ENOMEM;
case 2:
case 1: /* Open and reset log */
log_start += log_size;
log_size = 0;
return 0;
case 2: /* Read from log */
if (!buf || len < 0)
return -EINVAL;
if (!len)
return 0;
i = verify_area(VERIFY_WRITE, buf, len);
if (i)
return i;
verify_area(VERIFY_WRITE,buf,len);
while (!log_size) {
if (!log_page)
return -EIO;
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
cli();
......@@ -67,7 +76,7 @@ int sys_syslog(int type, char * buf, int len)
}
i = 0;
while (log_size && i < len) {
c = *((char *) log_page+log_start);
c = *((char *) log_buf+log_start);
log_start++;
log_size--;
log_start &= 4095;
......@@ -76,6 +85,36 @@ int sys_syslog(int type, char * buf, int len)
i++;
}
return i;
case 4: /* Read/clear last 4k of kernel messages */
do_clear = 1;
case 3: /* Read last 4k of kernel messages */
if (!buf || len < 0)
return -EINVAL;
if (!len)
return 0;
verify_area(VERIFY_WRITE,buf,len);
count = len;
if (count > 4096)
count = 4096;
if (count > logged_chars)
count = logged_chars;
j = log_start + log_size - count;
for (i = 0; i < count; i++) {
c = *((char *) log_buf + (j++ & 4095));
put_fs_byte(c, buf++);
}
if (do_clear)
logged_chars = 0;
return i;
case 5: /* Clear ring buffer */
logged_chars = 0;
return 0;
case 6: /* Disable logging to console */
log_to_console = 0;
return 0;
case 7: /* Enable logging to console */
log_to_console = 1;
return 0;
}
return -EINVAL;
}
......@@ -85,21 +124,47 @@ int printk(const char *fmt, ...)
{
va_list args;
int i,j;
char * p;
va_start(args, fmt);
i=vsprintf(buf,fmt,args);
va_end(args);
for (j = 0; j < i && log_page ; j++) {
p = (char *) log_page + (4095 & (log_start+log_size));
*p = buf[j];
for (j = 0; j < i ; j++) {
log_buf[(log_start+log_size) & 4095] = buf[j];
if (log_size < 4096)
log_size++;
else
log_start++;
logged_chars++;
}
if (log_page)
wake_up_interruptible(&log_wait);
console_print(buf);
wake_up_interruptible(&log_wait);
if (log_to_console && console_print_proc)
(*console_print_proc)(buf);
return i;
}
/*
* The console driver calls this routine during kernel initialization
* to register the console printing procedure with printk() and to
* print any messages that were printed by the kernel before the
* console priver was initialized.
*/
void register_console(void (*proc)(const char *))
{
int i,j;
int p = log_start;
char buf[16];
console_print_proc = proc;
for (i=0,j=0; i < log_size; i++) {
buf[j++] = log_buf[p];
p++; p &= 4095;
if (j < sizeof(buf)-1)
continue;
buf[j] = 0;
(*proc)(buf);
j = 0;
}
buf[j] = 0;
(*proc)(buf);
}
......@@ -159,8 +159,10 @@ int sys_pause(void)
if (sa->sa_handler == SIG_IGN || (sa->sa_handler == SIG_DFL
&& (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH)))
current->blocked |= mask;
current->state = TASK_INTERRUPTIBLE;
schedule();
do {
current->state = TASK_INTERRUPTIBLE;
schedule();
} while (!(current->signal & ~current->blocked));
/* if a suspending signal interrupted us we must restart */
if (!(current->signal & ~current->blocked &
~(_S(SIGSTOP) | _S(SIGTSTP) | _S(SIGTTIN) | _S(SIGTTOU)))) {
......
......@@ -170,87 +170,104 @@ extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
int do_signal(long signr,struct pt_regs * regs)
void do_signal(struct pt_regs * regs)
{
unsigned long signr;
unsigned long sa_handler;
long old_eip = regs->eip;
struct sigaction * sa = current->sigaction + signr - 1;
struct sigaction * sa;
int longs;
unsigned long * tmp_esp;
sa_handler = (unsigned long) sa->sa_handler;
if ((regs->orig_eax >= 0) &&
((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
if ((sa_handler > 1) && (regs->eax == -ERESTARTSYS) &&
(sa->sa_flags & SA_INTERRUPT))
regs->eax = -EINTR;
else {
regs->eax = regs->orig_eax;
regs->eip = old_eip -= 2;
}
if (regs->orig_eax >= 0 && regs->eax == -ERESTARTNOINTR) {
regs->eax = regs->orig_eax;
regs->eip = old_eip -= 2;
}
if (sa_handler==1) {
signr = current->signal & ~current->blocked;
do {
__asm__("bsf %2,%1\n\t"
"btrl %1,%0"
:"=m" (current->signal),"=r" (signr)
:"1" (signr));
sa = current->sigaction + signr;
signr++;
sa_handler = (unsigned long) sa->sa_handler;
if (sa_handler==1) {
/* check for SIGCHLD: it's special */
if (signr == SIGCHLD)
while (sys_waitpid(-1,NULL,WNOHANG) > 0)
/* nothing */;
return(1); /* Ignore, see if there are more signals... */
}
if (!sa_handler) {
if (current->pid == 1)
return 1;
switch (signr) {
case SIGCONT:
case SIGCHLD:
case SIGWINCH:
return(1); /* Ignore, ... */
if (signr == SIGCHLD)
while (sys_waitpid(-1,NULL,WNOHANG) > 0)
/* nothing */;
continue;
}
if (!sa_handler) {
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT:
case SIGCHLD:
case SIGWINCH:
continue;
case SIGSTOP:
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
send_sig(SIGCHLD, current->p_pptr, 1);
return(1); /* Reschedule another event */
case SIGSTOP:
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
send_sig(SIGCHLD, current->p_pptr, 1);
schedule();
continue;
case SIGQUIT:
case SIGILL:
case SIGTRAP:
case SIGIOT:
case SIGFPE:
case SIGSEGV:
if (core_dump(signr,regs))
signr |= 0x80;
/* fall through */
default:
current->signal |= _S(signr & 0x7f);
do_exit(signr);
case SIGQUIT:
case SIGILL:
case SIGTRAP:
case SIGIOT:
case SIGFPE:
case SIGSEGV:
if (core_dump(signr,regs))
signr |= 0x80;
/* fall through */
default:
current->signal |= _S(signr & 0x7f);
do_exit(signr);
}
}
}
/*
* OK, we're invoking a handler
*/
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
regs->eip = sa_handler;
longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
regs->esp -= longs;
tmp_esp = (unsigned long *) regs->esp;
verify_area(VERIFY_WRITE,tmp_esp,longs);
put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++);
put_fs_long(regs->eax,tmp_esp++);
put_fs_long(regs->ecx,tmp_esp++);
put_fs_long(regs->edx,tmp_esp++);
put_fs_long(regs->eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask;
/*
* OK, we're invoking a handler
*/
if (regs->orig_eax >= 0 && regs->eax == -ERESTARTSYS) {
if (sa->sa_flags & SA_INTERRUPT)
regs->eax = -EINTR;
else {
regs->eax = regs->orig_eax;
regs->eip = old_eip -= 2;
}
}
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
regs->eip = sa_handler;
longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
regs->esp -= longs;
tmp_esp = (unsigned long *) regs->esp;
verify_area(VERIFY_WRITE,tmp_esp,longs);
put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++);
put_fs_long(regs->eax,tmp_esp++);
put_fs_long(regs->ecx,tmp_esp++);
put_fs_long(regs->edx,tmp_esp++);
put_fs_long(regs->eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask;
/* force a supervisor-mode page-in of the signal handler to reduce races */
__asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler));
return(0); /* Continue, execute handler */
__asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler));
return;
} while ((signr = current->signal & ~current->blocked));
if (regs->orig_eax >= 0 && regs->eax == -ERESTARTSYS) {
regs->eax = regs->orig_eax;
regs->eip = old_eip -= 2;
}
}
......@@ -130,7 +130,12 @@ int sys_prof(void)
return -ENOSYS;
}
unsigned long save_v86_state(int signr,struct vm86_regs * regs)
int sys_ipc(void)
{
return -ENOSYS;
}
unsigned long save_v86_state(struct vm86_regs * regs)
{
unsigned long stack;
......
......@@ -65,23 +65,12 @@ VM_MASK = 0x00020000
/*
* these are offsets into the task-struct.
*/
state = 0
counter = 4
priority = 8
state = 0
counter = 4
priority = 8
signal = 12
sigaction = 16 # MUST be 16 (=len of sigaction)
blocked = (33*16)
saved_kernel_stack = ((33*16)+4)
kernel_stack_page = ((33*16)+8)
flags = ((33*16)+12)
/*
* offsets within sigaction
*/
sa_handler = 0
sa_mask = 4
sa_flags = 8
sa_restorer = 12
blocked = 16
flags = 20
ENOSYS = 38
......@@ -113,6 +102,21 @@ ENOSYS = 38
movl $0x17,%edx; \
mov %dx,%fs
#define RESTORE_ALL \
popl %ebx; \
popl %ecx; \
popl %edx; \
popl %esi; \
popl %edi; \
popl %ebp; \
popl %eax; \
pop %ds; \
pop %es; \
pop %fs; \
pop %gs; \
addl $4,%esp; \
iret
.align 4
reschedule:
pushl $ret_from_sys_call
......@@ -151,16 +155,16 @@ _system_call:
ret_from_sys_call:
movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
testl $VM_MASK,%eax # different then
jne 4f
jne 1f
cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
jne 2f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 2f
4: sti # slow interrupts get here with interrupts disabled
1: sti # slow interrupts get here with interrupts disabled
orl $IF_MASK,%eax # these just try to make sure
andl $~NT_MASK,%eax # the program doesn't do anything
movl %eax,EFLAGS(%esp) # stupid
1: cmpl $0,_need_resched
cmpl $0,_need_resched
jne reschedule
movl _current,%eax
cmpl _task,%eax # task[0] cannot have signals
......@@ -169,44 +173,28 @@ ret_from_sys_call:
jne reschedule
cmpl $0,counter(%eax) # counter
je reschedule
movl signal(%eax),%ebx
movl blocked(%eax),%ecx
notl %ecx
andl %ebx,%ecx
je 2f # XXX - branch is almost always taken
bsfl %ecx,%ecx
btrl %ecx,signal(%eax) # change atomically (%ebx is stale)
jnc 2f # bit became clear (can't happen?)
incl %ecx
andl signal(%eax),%ecx
jne signal_return
2: RESTORE_ALL
.align 4
signal_return:
movl %esp,%ebx
testl $VM_MASK,EFLAGS(%esp)
je 3f
pushl %ebx
pushl %ecx
testl $VM_MASK,EFLAGS(%ebx)
jne v86_signal_return
call _do_signal
popl %ebx
RESTORE_ALL
.align 4
v86_signal_return:
call _save_v86_state
popl %ecx
movl %eax,%ebx
movl %eax,%esp
3: pushl %ebx
pushl %ecx
pushl %eax
call _do_signal
popl %ecx
popl %ebx
testl %eax, %eax
jne 1b # see if we need to switch tasks, or do more signals
2: popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
popl %eax
pop %ds
pop %es
pop %fs
pop %gs
addl $4,%esp # skip the orig_eax
iret
RESTORE_ALL
.align 4
_sys_execve:
......
......@@ -563,10 +563,28 @@ void do_wp_page(unsigned long error_code, unsigned long address,
invalidate();
}
void write_verify(unsigned long address)
int verify_area(int type, void * addr, unsigned long size)
{
if (address < TASK_SIZE)
do_wp_page(1,address,current,0);
unsigned long start;
start = (unsigned long) addr;
if (start >= TASK_SIZE)
return -EFAULT;
if (size > TASK_SIZE - start)
return -EFAULT;
if (type == VERIFY_READ || !size)
return 0;
if (!size)
return 0;
size--;
size += start & 0xfff;
size >>= 12;
start &= 0xfffff000;
do {
do_wp_page(1,start,current,0);
start += 4096;
} while (size--);
return 0;
}
static void get_empty_page(struct task_struct * tsk, unsigned long address)
......
......@@ -662,7 +662,7 @@ int sys_swapon(const char * specialfile)
p->flags = 0;
return -ENOMEM;
}
read_swap_page(type < 1,tmp);
read_swap_page(SWP_ENTRY(type,0),tmp);
if (strncmp("SWAP-SPACE",tmp+4086,10)) {
printk("Unable to find swap-space signature\n");
free_page((long) tmp);
......
......@@ -317,40 +317,24 @@ arp_destroy(unsigned long paddr)
{
unsigned long hash;
struct arp_table *apt;
struct arp_table *lapt;
struct arp_table **lapt;
PRINTK (("arp_destroy (paddr=%X)\n",paddr));
/* we don't want to destroy are own arp */
if (my_ip_addr(paddr)) return;
hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
cli(); /* can't be interrupted. */
/* make sure there is something there. */
if (arp_table[hash] == NULL) return;
/* check the first one. */
if (arp_table[hash]->ip == paddr)
{
apt = (struct arp_table *)arp_table[hash];
arp_table[hash] = arp_table[hash]->next;
arp_free (apt, sizeof (*apt));
sti();
return;
}
/* now deal with it any where else in the chain. */
lapt = (struct arp_table *)arp_table[hash];
for (apt = (struct arp_table *)arp_table[hash]->next;
apt != NULL;
apt = (struct arp_table *)apt->next)
{
if (apt->ip == paddr)
{
lapt->next = apt->next;
arp_free (apt, sizeof (*apt));
sti();
return;
}
}
lapt = (struct arp_table **) &arp_table[hash];
while ((apt = *lapt) != NULL) {
if (apt->ip == paddr)
{
*lapt = (struct arp_table *) apt->next;
arp_free(apt, sizeof(*apt));
sti();
return;
}
lapt = (struct arp_table **) &apt->next;
}
sti();
}
......@@ -410,7 +394,7 @@ arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
tbl->last_used = timer_seq;
}
if (!my_ip_addr(*arp_targetp(arp)))
if (my_ip_addr(*arp_targetp(arp)) != IS_MYADDR)
{
kfree_skb (skb, FREE_READ);
return (0);
......
......@@ -192,7 +192,7 @@ int
ip_addr_match (unsigned long addr1, unsigned long addr2)
{
int i;
if (addr1 == addr2) return (1);
if (addr1 == addr2) return (IS_MYADDR);
for (i = 0; i < 4; i++, addr1 >>= 8, addr2 >>= 8)
{
if ((addr1 & 0xff) != (addr2 & 0xff))
......@@ -203,20 +203,22 @@ ip_addr_match (unsigned long addr1, unsigned long addr2)
{
return (0);
}
return (1);
return (IS_BROADCAST);
}
}
return (1);
return (IS_MYADDR);
}
int
my_ip_addr(unsigned long addr)
{
int i;
int result;
for (i = 0; i < MAX_IP_ADDRES; i++)
{
if (ip_addr[i] == 0) return (0);
if (ip_addr_match (addr, ip_addr[i])) return (1);
result = ip_addr_match (addr, ip_addr[i]);
if (result) return result;
}
return (0);
}
......
......@@ -156,6 +156,12 @@ extern int ip_ads;
#define MY_IP_ADDR ip_addr[0]
int my_ip_addr(unsigned long);
/*
* returned by my_ip_addr..
*/
#define IS_MYADDR 1
#define IS_BROADCAST 2
#include "eth.h"
void
......
......@@ -94,7 +94,14 @@ int main(int argc, char ** argv)
if ((argc < 4) || (argc > 5))
usage();
if (argc > 4) {
if (strcmp(argv[4], "FLOPPY")) {
if (!strcmp(argv[4], "CURRENT")) {
if (stat("/", &sb)) {
perror("/");
die("Couldn't stat /");
}
major_root = major(sb.st_dev);
minor_root = minor(sb.st_dev);
} else if (strcmp(argv[4], "FLOPPY")) {
if (stat(argv[4], &sb)) {
perror(argv[4]);
die("Couldn't stat root device.");
......
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