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 ...@@ -24,11 +24,11 @@ endif
# #
# ROOT_DEV specifies the default root-device when making the image. # ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
# default of FLOPPY is used by 'build'. # the default of FLOPPY is used by 'build'.
# #
ROOT_DEV = /dev/hdb1 ROOT_DEV = CURRENT
# #
# uncomment the correct keyboard: # uncomment the correct keyboard:
...@@ -45,20 +45,20 @@ ROOT_DEV = /dev/hdb1 ...@@ -45,20 +45,20 @@ ROOT_DEV = /dev/hdb1
# 0x10 - dieresis (umlaut) # 0x10 - dieresis (umlaut)
KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0 KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
# KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x9F # KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_US -DKBDFLAGS=0 # KEYBOARD = -DKBD_US -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR -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 -DKBDFLAGS=0
# KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x9F # KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_UK -DKBDFLAGS=0 # KEYBOARD = -DKBD_UK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK -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_DVORAK -DKBDFLAGS=0
# KEYBOARD = -DKBD_SG -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 -DKBDFLAGS=0
# KEYBOARD = -DKBD_SF_LATIN1 -DKBDFLAGS=0x9F # KEYBOARD = -DKBD_SF_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_NO -DKBDFLAGS=0 # KEYBOARD = -DKBD_NO -DKBDFLAGS=0
# #
...@@ -139,7 +139,7 @@ tools/./version.h: tools/version.h ...@@ -139,7 +139,7 @@ tools/./version.h: tools/version.h
tools/version.h: $(CONFIGURE) Makefile tools/version.h: $(CONFIGURE) Makefile
@./makever.sh @./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 UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
...@@ -232,9 +232,9 @@ clean: ...@@ -232,9 +232,9 @@ clean:
mrproper: clean mrproper: clean
rm -f include/linux/autoconf.h tools/version.h rm -f include/linux/autoconf.h tools/version.h
rm -f .version .config* 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 cd .. && tar cf - linux | gzip -9 > backup.z
sync sync
......
...@@ -4,6 +4,8 @@ Kernel math emulation ...@@ -4,6 +4,8 @@ Kernel math emulation
CONFIG_MATH_EMULATION y/n n CONFIG_MATH_EMULATION y/n n
Normal harddisk support Normal harddisk support
CONFIG_BLK_DEV_HD y/n y CONFIG_BLK_DEV_HD y/n y
XT harddisk support
CONFIG_BLK_DEV_XD y/n n
TCP/IP TCP/IP
CONFIG_TCPIP y/n y CONFIG_TCPIP y/n y
Kernel profiling support Kernel profiling support
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/errno.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -102,6 +103,11 @@ int sys_sync(void) ...@@ -102,6 +103,11 @@ int sys_sync(void)
return 0; return 0;
} }
int sys_fsync(int fd)
{
return -ENOSYS;
}
void invalidate_buffers(dev_t dev) void invalidate_buffers(dev_t dev)
{ {
int i; int i;
...@@ -358,7 +364,7 @@ struct buffer_head * getblk(dev_t dev, int block, int size) ...@@ -358,7 +364,7 @@ struct buffer_head * getblk(dev_t dev, int block, int size)
if (bh->b_count || bh->b_size != size) if (bh->b_count || bh->b_size != size)
goto repeat; goto repeat;
if (bh->b_dirt) { if (bh->b_dirt) {
sync_buffers(bh->b_dev); sync_buffers(0);
goto repeat; goto repeat;
} }
/* NOTE!! While we slept waiting for this block, somebody else might */ /* 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, ...@@ -460,7 +460,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
} }
i = inode->i_mode; i = inode->i_mode;
if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current-> 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()) { !suser()) {
retval = -EPERM; retval = -EPERM;
goto exec_error2; goto exec_error2;
......
...@@ -48,7 +48,6 @@ static int ext_follow_link(struct inode * dir, struct inode * inode, ...@@ -48,7 +48,6 @@ static int ext_follow_link(struct inode * dir, struct inode * inode,
int flag, int mode, struct inode ** res_inode) int flag, int mode, struct inode ** res_inode)
{ {
int error; int error;
unsigned short fs;
struct buffer_head * bh; struct buffer_head * bh;
*res_inode = NULL; *res_inode = NULL;
......
...@@ -376,6 +376,7 @@ static int empty_dir(struct inode * inode) ...@@ -376,6 +376,7 @@ static int empty_dir(struct inode * inode)
return 1; return 1;
info = &inode->i_sb->u.minix_sb; info = &inode->i_sb->u.minix_sb;
block = 0; block = 0;
bh = NULL;
offset = 2*info->s_dirsize; offset = 2*info->s_dirsize;
if (inode->i_size & (info->s_dirsize-1)) if (inode->i_size & (info->s_dirsize-1))
goto bad_dir; goto bad_dir;
......
/* /*
* linux/fs/msdos/dir.c * linux/fs/msdos/dir.c
* *
* Written 1992 by Werner Almesberger * Written 1992,1993 by Werner Almesberger
* *
* MS-DOS directory handling functions * MS-DOS directory handling functions
*/ */
#include <asm/segment.h> #include <asm/segment.h>
#include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/stat.h> #include <linux/stat.h>
static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count) static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
{ {
return -EISDIR; return -EISDIR;
...@@ -22,6 +22,7 @@ static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,in ...@@ -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, static int msdos_readdir(struct inode *inode,struct file *filp,
struct dirent *dirent,int count); struct dirent *dirent,int count);
static struct file_operations msdos_dir_operations = { static struct file_operations msdos_dir_operations = {
NULL, /* lseek - default */ NULL, /* lseek - default */
msdos_dir_read, /* read */ msdos_dir_read, /* read */
...@@ -78,8 +79,7 @@ static int msdos_readdir(struct inode *inode,struct file *filp, ...@@ -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; if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
bh = NULL; bh = NULL;
while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) { while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
if (de->name[0] && ((unsigned char *) (de->name))[0] != if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
DELETED_FLAG && !(de->attr & ATTR_VOLUME)) {
for (i = last = 0; i < 8; i++) { for (i = last = 0; i < 8; i++) {
if (!(c = de->name[i])) break; if (!(c = de->name[i])) break;
if (c >= 'A' && c <= 'Z') c += 32; if (c >= 'A' && c <= 'Z') c += 32;
......
/* /*
* linux/fs/msdos/fat.c * linux/fs/msdos/fat.c
* *
* Written 1992 by Werner Almesberger * Written 1992,1993 by Werner Almesberger
*/ */
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
...@@ -22,6 +22,7 @@ int fat_access(struct super_block *sb,int this,int new_value) ...@@ -22,6 +22,7 @@ int fat_access(struct super_block *sb,int this,int new_value)
void *data,*data2,*c_data,*c_data2; void *data,*data2,*c_data,*c_data2;
int first,last,next,copy; 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; if (MSDOS_SB(sb)->fat_bits == 16) first = last = this*2;
else { else {
first = this*3/2; first = this*3/2;
...@@ -46,9 +47,9 @@ int fat_access(struct super_block *sb,int this,int new_value) ...@@ -46,9 +47,9 @@ int fat_access(struct super_block *sb,int this,int new_value)
} }
if (MSDOS_SB(sb)->fat_bits == 16) { if (MSDOS_SB(sb)->fat_bits == 16) {
p_first = p_last = NULL; /* GCC needs that stuff */ p_first = p_last = NULL; /* GCC needs that stuff */
next = ((unsigned short *) data)[(first & (SECTOR_SIZE-1)) next = CF_LE_W(((unsigned short *) data)[(first &
>> 1]; (SECTOR_SIZE-1)) >> 1]);
if (next >= 0xfff8) next = -1; if (next >= 0xfff7) next = -1;
} }
else { else {
p_first = &((unsigned char *) data)[first & (SECTOR_SIZE-1)]; 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) ...@@ -56,12 +57,12 @@ int fat_access(struct super_block *sb,int this,int new_value)
(SECTOR_SIZE-1)]; (SECTOR_SIZE-1)];
if (this & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff; if (this & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
else next = (*p_first+(*p_last << 8)) & 0xfff; else next = (*p_first+(*p_last << 8)) & 0xfff;
if (next >= 0xff8) next = -1; if (next >= 0xff7) next = -1;
} }
if (new_value != -1) { if (new_value != -1) {
if (MSDOS_SB(sb)->fat_bits == 16) if (MSDOS_SB(sb)->fat_bits == 16)
((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >> ((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >>
1] = new_value; 1] = CT_LE_W(new_value);
else { else {
if (this & 1) { if (this & 1) {
*p_first = (*p_first & 0xf) | (new_value << 4); *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); ...@@ -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) for (walk = fat_cache; walk->next; walk = (last = walk)->next)
if (inode->i_dev == walk->device && walk->ino == inode->i_ino && if (inode->i_dev == walk->device && walk->ino == inode->i_ino &&
walk->file_cluster == f_clu) { walk->file_cluster == f_clu) {
if (walk->disk_cluster != d_clu) if (walk->disk_cluster != d_clu) {
panic("FAT cache corruption"); printk("FAT cache corruption");
cache_inval_inode(inode);
return;
}
/* update LRU */ /* update LRU */
if (last == NULL) return; if (last == NULL) return;
last->next = walk->next; last->next = walk->next;
...@@ -226,10 +230,7 @@ int get_cluster(struct inode *inode,int cluster) ...@@ -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 = fat_access(inode->i_sb,this,-1)) == -1) return 0;
if (!this) return 0; if (!this) return 0;
} }
if (!(MSDOS_I(inode)->i_busy && inode->i_nlink)) cache_add(inode,cluster,this);
cache_add(inode,cluster,this);
/* don't add clusters of moved files, because we can't invalidate them
when this inode is returned. */
return this; return this;
} }
...@@ -278,8 +279,10 @@ int fat_free(struct inode *inode,int skip) ...@@ -278,8 +279,10 @@ int fat_free(struct inode *inode,int skip)
} }
lock_fat(inode->i_sb); lock_fat(inode->i_sb);
while (this != -1) { while (this != -1) {
if (!(this = fat_access(inode->i_sb,this,0))) if (!(this = fat_access(inode->i_sb,this,0))) {
panic("fat_free: deleting beyond EOF"); fs_panic(inode->i_sb,"fat_free: deleting beyond EOF");
break;
}
if (MSDOS_SB(inode->i_sb)->free_clusters != -1) if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
MSDOS_SB(inode->i_sb)->free_clusters++; MSDOS_SB(inode->i_sb)->free_clusters++;
inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size; inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
......
/* /*
* linux/fs/msdos/file.c * linux/fs/msdos/file.c
* *
* Written 1992 by Werner Almesberger * Written 1992,1993 by Werner Almesberger
* *
* MS-DOS regular file handling primitives * MS-DOS regular file handling primitives
*/ */
......
This diff is collapsed.
This diff is collapsed.
/* /*
* linux/fs/msdos/namei.c * linux/fs/msdos/namei.c
* *
* Written 1992 by Werner Almesberger * Written 1992,1993 by Werner Almesberger
*/ */
#include <asm/segment.h> #include <asm/segment.h>
...@@ -25,35 +25,33 @@ static char *reserved_names[] = { ...@@ -25,35 +25,33 @@ static char *reserved_names[] = {
/* Characters that are undesirable in an MS-DOS file name */ /* Characters that are undesirable in an MS-DOS file name */
static char bad_chars[] = "*?<>|\""; static char bad_chars[] = "*?<>|\"";
static char bad_if_strict[] = "+=,;"; static char bad_if_strict[] = "+=,; ";
/* Formats an MS-DOS file name. Rejects invalid names. */ /* 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 *walk,**reserved;
char c; char c;
int space; int space;
if (*(unsigned char *)name == DELETED_FLAG) return -EINVAL; if (IS_FREE(name)) return -EINVAL;
if (name[0] == '.' && (len == 1 || (len == 2 && if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
name[1] == '.'))) { if (!dot_dirs) return -EEXIST;
memset(res+1,' ',10); memset(res+1,' ',10);
while (len--) *res++ = '.'; while (len--) *res++ = '.';
return 0; return 0;
} }
space = 0; /* to make GCC happy */ space = 1; /* disallow names starting with a dot */
c = 0; c = 0;
for (walk = res; len && walk-res < 8; walk++) { for (walk = res; len && walk-res < 8; walk++) {
c = *(name++); c = *name++;
len--; len--;
if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL; if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL; if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
if (c >= 'A' && c <= 'Z') { if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
if (conv == 's') return -EINVAL;
c += 32;
}
if (c < ' ' || c == ':' || c == '\\') return -EINVAL; if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
if (c == '.') break; if (c == '.') break;
space = c == ' '; space = c == ' ';
...@@ -61,26 +59,22 @@ static int msdos_format_name(char conv,const char *name,int len,char *res) ...@@ -61,26 +59,22 @@ static int msdos_format_name(char conv,const char *name,int len,char *res)
} }
if (space) return -EINVAL; if (space) return -EINVAL;
if (conv == 's' && len && c != '.') { if (conv == 's' && len && c != '.') {
c = *(name++); c = *name++;
len--; len--;
if (c != '.') return -EINVAL; if (c != '.') return -EINVAL;
} }
while (c != '.' && len--) c = *(name++); while (c != '.' && len--) c = *name++;
if (walk == res) return -EINVAL;
if (c == '.') { if (c == '.') {
while (walk-res < 8) *walk++ = ' '; while (walk-res < 8) *walk++ = ' ';
while (len > 0 && walk-res < MSDOS_NAME) { while (len > 0 && walk-res < MSDOS_NAME) {
c = *(name++); c = *name++;
len--; len--;
if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL; if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
if (conv == 's' && strchr(bad_if_strict,c)) if (conv == 's' && strchr(bad_if_strict,c))
return -EINVAL; return -EINVAL;
if (c < ' ' || c == ':' || c == '\\' || c == '.') if (c < ' ' || c == ':' || c == '\\' || c == '.')
return -EINVAL; return -EINVAL;
if (c >= 'A' && c <= 'Z') { if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
if (conv == 's') return -EINVAL;
c += 32;
}
space = c == ' '; space = c == ' ';
*walk++ = c >= 'a' && c <= 'z' ? c-32 : 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, ...@@ -103,7 +97,7 @@ static int msdos_find(struct inode *dir,const char *name,int len,
int res; int res;
if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, 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); return msdos_scan(dir,msdos_name,bh,de,ino);
} }
...@@ -126,8 +120,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len, ...@@ -126,8 +120,7 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
*result = dir; *result = dir;
return 0; return 0;
} }
if (len == 2 && name[0] == '.' && name[1] == '.') if (len == 2 && name[0] == '.' && name[1] == '.') {
{
ino = msdos_parent_ino(dir,0); ino = msdos_parent_ino(dir,0);
iput(dir); iput(dir);
if (ino < 0) return ino; if (ino < 0) return ino;
...@@ -152,8 +145,11 @@ int msdos_lookup(struct inode *dir,const char *name,int len, ...@@ -152,8 +145,11 @@ int msdos_lookup(struct inode *dir,const char *name,int len,
while (MSDOS_I(*result)->i_old) { while (MSDOS_I(*result)->i_old) {
next = MSDOS_I(*result)->i_old; next = MSDOS_I(*result)->i_old;
iput(*result); iput(*result);
if (!(*result = iget(next->i_sb,next->i_ino))) if (!(*result = iget(next->i_sb,next->i_ino))) {
panic("msdos_lookup: Can't happen"); fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
iput(dir);
return -ENOENT;
}
} }
iput(dir); iput(dir);
return 0; return 0;
...@@ -170,6 +166,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir, ...@@ -170,6 +166,7 @@ static int msdos_create_entry(struct inode *dir,char *name,int is_dir,
int res,ino; int res,ino;
if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) { 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 (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
if ((res = msdos_add_cluster(dir)) < 0) return res; if ((res = msdos_add_cluster(dir)) < 0) return res;
if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 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, ...@@ -201,7 +198,7 @@ int msdos_create(struct inode *dir,const char *name,int len,int mode,
if (!dir) return -ENOENT; if (!dir) return -ENOENT;
if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
msdos_name)) < 0) { msdos_name,0)) < 0) {
iput(dir); iput(dir);
return res; return res;
} }
...@@ -226,7 +223,7 @@ static void dump_fat(struct super_block *sb,int start) ...@@ -226,7 +223,7 @@ static void dump_fat(struct super_block *sb,int start)
printk("["); printk("[");
while (start) { while (start) {
printk("%d ",start); printk("%d ",start);
start = fat_access(sb,start,-1); start = fat_access(sb,start,-1);
if (!start) { if (!start) {
printk("ERROR"); printk("ERROR");
break; break;
...@@ -248,7 +245,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode) ...@@ -248,7 +245,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
int ino,res; int ino,res;
if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
msdos_name)) < 0) { msdos_name,0)) < 0) {
iput(dir); iput(dir);
return res; return res;
} }
...@@ -289,7 +286,8 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode) ...@@ -289,7 +286,8 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
return 0; return 0;
mkdir_error: mkdir_error:
iput(inode); 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(); unlock_creation();
return res; return res;
} }
...@@ -304,9 +302,9 @@ int msdos_rmdir(struct inode *dir,const char *name,int len) ...@@ -304,9 +302,9 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
bh = NULL; bh = NULL;
inode = NULL; inode = NULL;
res = -EINVAL; res = -EPERM;
if (name[0] == '.' && (len == 1 || (len == 2 && if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
name[1] == '.'))) goto rmdir_done; goto rmdir_done;
if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done; if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
res = -ENOENT; res = -ENOENT;
if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done; 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) ...@@ -320,8 +318,7 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
pos = 0; pos = 0;
dbh = NULL; dbh = NULL;
while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1) while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1)
if (dde->name[0] && ((unsigned char *) dde->name)[0] != if (!IS_FREE(dde->name) && strncmp(dde->name,MSDOS_DOT,
DELETED_FLAG && strncmp(dde->name,MSDOS_DOT,
MSDOS_NAME) && strncmp(dde->name,MSDOS_DOTDOT, MSDOS_NAME) && strncmp(dde->name,MSDOS_DOTDOT,
MSDOS_NAME)) goto rmdir_done; MSDOS_NAME)) goto rmdir_done;
if (dbh) brelse(dbh); if (dbh) brelse(dbh);
...@@ -439,10 +436,13 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name, ...@@ -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; if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
} }
iput(walk); iput(walk);
if ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) < 0) while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) <
return error; 0) {
exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) if (error != -ENOENT) return error;
>= 0; 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))) { if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
brelse(free_bh); brelse(free_bh);
if (exists) brelse(new_bh); if (exists) brelse(new_bh);
...@@ -536,9 +536,9 @@ int msdos_rename(struct inode *old_dir,const char *old_name,int old_len, ...@@ -536,9 +536,9 @@ int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
int old_ino,error; int old_ino,error;
if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check, 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, 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, if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
&old_ino)) < 0) goto rename_done; &old_ino)) < 0) goto rename_done;
lock_creation(); lock_creation();
......
...@@ -330,7 +330,8 @@ struct inode * xiafs_new_inode(struct inode * dir) ...@@ -330,7 +330,8 @@ struct inode * xiafs_new_inode(struct inode * dir)
inode->i_ino = tmp; inode->i_ino = tmp;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL; 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; return inode;
} }
......
...@@ -101,8 +101,10 @@ static int xiafs_readdir(struct inode * inode, ...@@ -101,8 +101,10 @@ static int xiafs_readdir(struct inode * inode,
put_fs_long(de->d_ino,&dirent->d_ino); put_fs_long(de->d_ino,&dirent->d_ino);
put_fs_word(i,&dirent->d_reclen); put_fs_word(i,&dirent->d_reclen);
brelse(bh); brelse(bh);
inode->i_atime=CURRENT_TIME; if (!IS_RDONLY (inode)) {
inode->i_dirt=1; inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
return i; return i;
} }
de = (struct xiafs_direct *) (offset + bh->b_data); de = (struct xiafs_direct *) (offset + bh->b_data);
...@@ -113,9 +115,9 @@ static int xiafs_readdir(struct inode * inode, ...@@ -113,9 +115,9 @@ static int xiafs_readdir(struct inode * inode,
return 0; return 0;
} }
} }
inode->i_atime=CURRENT_TIME; if (!IS_RDONLY (inode)) {
inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
return 0; return 0;
} }
...@@ -175,9 +175,10 @@ xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -175,9 +175,10 @@ xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
if (!read) if (!read)
return -EIO; return -EIO;
filp->f_reada = 1; filp->f_reada = 1;
inode->i_atime = CURRENT_TIME; if (!IS_RDONLY (inode)) {
inode->i_dirt = 1; inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
return read; return read;
} }
...@@ -239,7 +240,7 @@ xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count ...@@ -239,7 +240,7 @@ xiafs_file_write(struct inode * inode, struct file * filp, char * buf, int count
bh->b_dirt = 1; bh->b_dirt = 1;
brelse(bh); brelse(bh);
} }
inode->i_mtime = CURRENT_TIME; inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
filp->f_pos = pos; filp->f_pos = pos;
inode->i_dirt = 1; inode->i_dirt = 1;
......
...@@ -176,8 +176,10 @@ int xiafs_bmap(struct inode * inode,int zone) ...@@ -176,8 +176,10 @@ int xiafs_bmap(struct inode * inode,int zone)
printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR); printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
return 0; return 0;
} }
inode->i_atime = CURRENT_TIME; if (!IS_RDONLY (inode)) {
inode->i_dirt = 1; inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
}
if (zone < 8) if (zone < 8)
return inode->u.xiafs_i.i_zone[zone]; return inode->u.xiafs_i.i_zone[zone];
zone -= 8; zone -= 8;
...@@ -236,6 +238,7 @@ dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr) ...@@ -236,6 +238,7 @@ dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr)
goto repeat; goto repeat;
} }
*lp = tmp; *lp = tmp;
inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
return result; return result;
} }
...@@ -279,17 +282,18 @@ indt_getblk(struct inode * inode, struct buffer_head * bh, ...@@ -279,17 +282,18 @@ indt_getblk(struct inode * inode, struct buffer_head * bh,
} }
result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb)); result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
if (*lp) { if (*lp) {
xiafs_free_zone(inode->i_sb,tmp); xiafs_free_zone(inode->i_sb, tmp);
brelse(result); brelse(result);
goto repeat; goto repeat;
} }
*lp = tmp; *lp = tmp;
inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
bh->b_dirt = 1; bh->b_dirt = 1;
brelse(bh); brelse(bh);
return result; 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; struct buffer_head * bh;
u_long prev_addr=0; u_long prev_addr=0;
...@@ -368,15 +372,16 @@ void xiafs_read_inode(struct inode * inode) ...@@ -368,15 +372,16 @@ void xiafs_read_inode(struct inode * inode)
inode->i_mtime = raw_inode->i_mtime; inode->i_mtime = raw_inode->i_mtime;
inode->i_atime = raw_inode->i_atime; inode->i_atime = raw_inode->i_atime;
inode->i_ctime = raw_inode->i_ctime; inode->i_ctime = raw_inode->i_ctime;
inode->i_blocks = 0; inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
inode->i_blksize = 0; /* let vfs estimate */ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_blocks=0;
inode->i_rdev = raw_inode->i_zone[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++) for (zone = 0; zone < 8; zone++)
inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[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; 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; inode->u.xiafs_i.i_dind_zone = raw_inode->i_dind_zone & 0xffffff;
} }
brelse(bh); brelse(bh);
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
...@@ -406,6 +411,12 @@ void xiafs_write_inode(struct inode * inode) ...@@ -406,6 +411,12 @@ void xiafs_write_inode(struct inode * inode)
int zone; int zone;
ino_t ino; 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; ino = inode->i_ino;
if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) { if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR); printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
...@@ -427,20 +438,20 @@ void xiafs_write_inode(struct inode * inode) ...@@ -427,20 +438,20 @@ void xiafs_write_inode(struct inode * inode)
raw_inode->i_gid = inode->i_gid; raw_inode->i_gid = inode->i_gid;
raw_inode->i_nlinks = inode->i_nlink; raw_inode->i_nlinks = inode->i_nlink;
raw_inode->i_size = inode->i_size; 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_atime = inode->i_atime;
raw_inode->i_ctime = inode->i_ctime; raw_inode->i_ctime = inode->i_ctime;
raw_inode->i_mtime = inode->i_mtime; raw_inode->i_mtime = inode->i_mtime;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = inode->i_rdev; raw_inode->i_zone[0] = inode->i_rdev;
else { else {
XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks);
for (zone = 0; zone < 8; zone++) for (zone = 0; zone < 8; zone++)
raw_inode->i_zone[zone] = inode->u.xiafs_i.i_zone[zone]; raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000)
raw_inode->i_ind_zone = inode->u.xiafs_i.i_ind_zone; | (inode->u.xiafs_i.i_zone[zone] & 0xffffff);
raw_inode->i_dind_zone = inode->u.xiafs_i.i_dind_zone; 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; inode->i_dirt=0;
bh->b_dirt=1; bh->b_dirt=1;
......
...@@ -212,7 +212,7 @@ static struct buffer_head * xiafs_add_entry(struct inode * dir, ...@@ -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) { 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; dir->i_dirt = 1;
memcpy(de->d_name, name, namelen); memcpy(de->d_name, name, namelen);
de->d_name[namelen]=0; de->d_name[namelen]=0;
...@@ -316,7 +316,7 @@ int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev ...@@ -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)) if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = rdev; 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; inode->i_dirt = 1;
bh = xiafs_add_entry(dir, name, len, &de, NULL); bh = xiafs_add_entry(dir, name, len, &de, NULL);
if (!bh) { if (!bh) {
...@@ -357,7 +357,7 @@ int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -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_op = &xiafs_dir_inode_operations;
inode->i_size = XIAFS_ZSIZE(dir->i_sb); 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); dir_block = xiafs_bread(inode,0,1);
if (!dir_block) { if (!dir_block) {
iput(dir); iput(dir);
...@@ -524,7 +524,7 @@ int xiafs_rmdir(struct inode * dir, const char * name, int len) ...@@ -524,7 +524,7 @@ int xiafs_rmdir(struct inode * dir, const char * name, int len)
inode->i_nlink=0; inode->i_nlink=0;
inode->i_dirt=1; inode->i_dirt=1;
dir->i_nlink--; dir->i_nlink--;
dir->i_mtime = CURRENT_TIME; dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt=1; dir->i_dirt=1;
retval = 0; retval = 0;
end_rmdir: end_rmdir:
...@@ -569,10 +569,9 @@ int xiafs_unlink(struct inode * dir, const char * name, int len) ...@@ -569,10 +569,9 @@ int xiafs_unlink(struct inode * dir, const char * name, int len)
} }
xiafs_rm_entry(de, de_pre); xiafs_rm_entry(de, de_pre);
bh->b_dirt = 1; bh->b_dirt = 1;
dir->i_mtime = CURRENT_TIME; dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1; dir->i_dirt = 1;
inode->i_nlink--; inode->i_nlink--;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1; inode->i_dirt = 1;
retval = 0; retval = 0;
end_unlink: end_unlink:
...@@ -668,7 +667,7 @@ int xiafs_link(struct inode * oldinode, struct inode * dir, ...@@ -668,7 +667,7 @@ int xiafs_link(struct inode * oldinode, struct inode * dir,
brelse(bh); brelse(bh);
iput(dir); iput(dir);
oldinode->i_nlink++; oldinode->i_nlink++;
oldinode->i_ctime = CURRENT_TIME; oldinode->i_atime = oldinode->i_ctime = CURRENT_TIME;
oldinode->i_dirt = 1; oldinode->i_dirt = 1;
iput(oldinode); iput(oldinode);
return 0; return 0;
......
...@@ -57,8 +57,10 @@ static int xiafs_readlink(struct inode * inode, char * buffer, int buflen) ...@@ -57,8 +57,10 @@ static int xiafs_readlink(struct inode * inode, char * buffer, int buflen)
if (buflen > BLOCK_SIZE) if (buflen > BLOCK_SIZE)
buflen = BLOCK_SIZE; buflen = BLOCK_SIZE;
bh = xiafs_bread(inode, 0, 0); bh = xiafs_bread(inode, 0, 0);
inode->i_atime=CURRENT_TIME; if (!IS_RDONLY (inode)) {
inode->i_dirt=1; inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
iput(inode); iput(inode);
if (!bh) if (!bh)
return 0; return 0;
...@@ -90,8 +92,10 @@ static int xiafs_follow_link(struct inode * dir, struct inode * inode, ...@@ -90,8 +92,10 @@ static int xiafs_follow_link(struct inode * dir, struct inode * inode,
*res_inode = inode; *res_inode = inode;
return 0; return 0;
} }
inode->i_atime=CURRENT_TIME; if (!IS_RDONLY (inode)) {
inode->i_dirt=1; inode->i_atime=CURRENT_TIME;
inode->i_dirt=1;
}
if (current->link_count > 5) { if (current->link_count > 5) {
iput(inode); iput(inode);
iput(dir); iput(dir);
......
...@@ -60,6 +60,7 @@ static int trunc_direct(struct inode * inode) ...@@ -60,6 +60,7 @@ static int trunc_direct(struct inode * inode)
else { else {
*lp = 0; *lp = 0;
inode->i_dirt = 1; inode->i_dirt = 1;
inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp); xiafs_free_zone(inode->i_sb, tmp);
} }
brelse(bh); brelse(bh);
...@@ -105,6 +106,7 @@ static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp) ...@@ -105,6 +106,7 @@ static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
else { else {
*indp = 0; *indp = 0;
ind_bh->b_dirt = 1; ind_bh->b_dirt = 1;
inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp); xiafs_free_zone(inode->i_sb, tmp);
} }
brelse(bh); brelse(bh);
...@@ -117,6 +119,7 @@ static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp) ...@@ -117,6 +119,7 @@ static int trunc_indirect(struct inode * inode, int addr_off, u_long * lp)
else { else {
tmp = *lp; tmp = *lp;
*lp = 0; *lp = 0;
inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp); xiafs_free_zone(inode->i_sb, tmp);
} }
} }
...@@ -166,6 +169,7 @@ static int trunc_dindirect(struct inode * inode) ...@@ -166,6 +169,7 @@ static int trunc_dindirect(struct inode * inode)
tmp = *lp; tmp = *lp;
*lp = 0; *lp = 0;
inode->i_dirt = 1; inode->i_dirt = 1;
inode->i_blocks-=2 << XIAFS_ZSHIFT(inode->i_sb);
xiafs_free_zone(inode->i_sb, tmp); xiafs_free_zone(inode->i_sb, tmp);
} }
} }
...@@ -189,7 +193,7 @@ void xiafs_truncate(struct inode * inode) ...@@ -189,7 +193,7 @@ void xiafs_truncate(struct inode * inode)
current->counter = 0; current->counter = 0;
schedule(); schedule();
} }
inode->i_mtime = CURRENT_TIME; inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1; inode->i_dirt = 1;
} }
......
...@@ -17,4 +17,16 @@ extern char internal_error_message[]; ...@@ -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_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)) #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); ...@@ -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 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 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 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, extern void do_wp_page(unsigned long error_code, unsigned long address,
struct task_struct *tsk, unsigned long user_esp); struct task_struct *tsk, unsigned long user_esp);
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/stat.h>
#include <linux/fd.h>
#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ #define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */
#define SECTOR_SIZE 512 /* sector size (bytes) */ #define SECTOR_SIZE 512 /* sector size (bytes) */
...@@ -32,6 +34,11 @@ ...@@ -32,6 +34,11 @@
/* attribute bits that are copied "as is" */ /* attribute bits that are copied "as is" */
#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ #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_SB(s) (&((s)->u.msdos_sb))
#define MSDOS_I(i) (&((i)->u.msdos_i)) #define MSDOS_I(i) (&((i)->u.msdos_i))
...@@ -40,10 +47,26 @@ ...@@ -40,10 +47,26 @@
#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ #define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
#define MSDOS_DOTDOT ".. " /* "..", 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 { 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 char cluster_size; /* sectors/cluster */
unsigned short reserved; /* reserved sectors */ unsigned short reserved; /* reserved sectors */
unsigned char fats; /* number of FATs */ unsigned char fats; /* number of FATs */
...@@ -51,8 +74,8 @@ struct msdos_boot_sector { ...@@ -51,8 +74,8 @@ struct msdos_boot_sector {
unsigned char sectors[2]; /* number of sectors */ unsigned char sectors[2]; /* number of sectors */
unsigned char media; /* media code (unused) */ unsigned char media; /* media code (unused) */
unsigned short fat_length; /* sectors/FAT */ unsigned short fat_length; /* sectors/FAT */
unsigned short secs_track; /* sectors per track (unused) */ unsigned short secs_track; /* sectors per track */
unsigned short heads; /* number of heads (unused) */ unsigned short heads; /* number of heads */
unsigned long hidden; /* hidden sectors (unused) */ unsigned long hidden; /* hidden sectors (unused) */
unsigned long total_sect; /* number of sectors (if sectors == 0) */ unsigned long total_sect; /* number of sectors (if sectors == 0) */
}; };
...@@ -80,11 +103,11 @@ struct fat_cache { ...@@ -80,11 +103,11 @@ struct fat_cache {
/* Convert attribute bits and a mask to the UNIX mode. */ /* 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. */ /* 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) 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) ...@@ -100,6 +123,7 @@ static inline struct buffer_head *msdos_sread(int dev,int sector,void **start)
/* misc.c */ /* misc.c */
extern void fs_panic(struct super_block *s,char *msg);
extern int is_binary(char conversion,char *extension); extern int is_binary(char conversion,char *extension);
extern void lock_creation(void); extern void lock_creation(void);
extern void unlock_creation(void); extern void unlock_creation(void);
...@@ -149,6 +173,7 @@ extern void msdos_statfs(struct super_block *sb,struct statfs *buf); ...@@ -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 int msdos_bmap(struct inode *inode,int block);
extern void msdos_read_inode(struct inode *inode); extern void msdos_read_inode(struct inode *inode);
extern void msdos_write_inode(struct inode *inode); extern void msdos_write_inode(struct inode *inode);
extern int msdos_notify_change(int flags,struct inode *inode);
/* dir.c */ /* dir.c */
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
#define _MSDOS_FS_I #define _MSDOS_FS_I
/* /*
* msdos file system inode data in memory * MS-DOS file system inode data in memory
*/ */
struct msdos_inode_info { struct msdos_inode_info {
int i_start; /* first cluster or 0 */ int i_start; /* first cluster or 0 */
int i_attrs; /* unused attribute bits */ int i_attrs; /* unused attribute bits */
......
#ifndef _MSDOS_FS_SB #ifndef _MSDOS_FS_SB
#define _MSDOS_FS_SB #define _MSDOS_FS_SB
/*
* MS-DOS file system in-core superblock data
*/
struct msdos_sb_info { struct msdos_sb_info {
unsigned short cluster_size; /* sectors/cluster */ unsigned short cluster_size; /* sectors/cluster */
unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
...@@ -15,6 +19,7 @@ struct msdos_sb_info { ...@@ -15,6 +19,7 @@ struct msdos_sb_info {
unsigned char conversion; /* b = binary, t = text, a = auto */ unsigned char conversion; /* b = binary, t = text, a = auto */
struct wait_queue *fat_wait; struct wait_queue *fat_wait;
int fat_lock; int fat_lock;
int prev_free; /* previously returned free cluster number */
int free_clusters; /* -1 if undefined */ int free_clusters; /* -1 if undefined */
}; };
......
...@@ -143,16 +143,16 @@ struct tss_struct { ...@@ -143,16 +143,16 @@ struct tss_struct {
struct task_struct { struct task_struct {
/* these are hardcoded - don't touch */ /* 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 counter;
long priority; 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]; struct sigaction sigaction[32];
long blocked; /* bitmap of masked signals */
unsigned long saved_kernel_stack; unsigned long saved_kernel_stack;
unsigned long kernel_stack_page; unsigned long kernel_stack_page;
unsigned int flags; /* per process flags, defined below */
/* various fields */
int exit_code; int exit_code;
int dumpable:1; int dumpable:1;
int swappable:1; int swappable:1;
...@@ -220,9 +220,9 @@ struct task_struct { ...@@ -220,9 +220,9 @@ struct task_struct {
* your own risk!. Base=0, limit=0x1fffff (=2MB) * your own risk!. Base=0, limit=0x1fffff (=2MB)
*/ */
#define INIT_TASK \ #define INIT_TASK \
/* state etc */ { 0,15,15, \ /* state etc */ { 0,15,15,0,0,0, \
/* signals */ 0,{{ 0, },},0,0,0, \ /* signals */ {{ 0, },}, \
/* flags */ 0, \ /* stack */ 0,0, \
/* ec,brk... */ 0,0,0,0,0,0,0,0, \ /* ec,brk... */ 0,0,0,0,0,0,0,0, \
/* argv.. */ 0,0,0,0, \ /* argv.. */ 0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \ /* pid etc.. */ 0,0,0,0, \
...@@ -275,7 +275,7 @@ extern void interruptible_sleep_on(struct wait_queue ** p); ...@@ -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(struct wait_queue ** p);
extern void wake_up_interruptible(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 in_group_p(gid_t grp);
extern int request_irq(unsigned int irq,void (*handler)(int)); extern int request_irq(unsigned int irq,void (*handler)(int));
......
...@@ -119,6 +119,8 @@ extern int sys_vm86(); ...@@ -119,6 +119,8 @@ extern int sys_vm86();
extern int sys_wait4(); extern int sys_wait4();
extern int sys_swapoff(); extern int sys_swapoff();
extern int sys_sysinfo(); 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, 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, 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, ...@@ -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_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_socketcall,
sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
sys_newfstat, sys_newuname, sys_iopl, sys_vhangup, sys_idle, sys_vm86, 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.... */ /* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* SCSI_TIMER scsi.c timeout timer * SCSI_TIMER scsi.c timeout timer
* *
* NET_TIMER tcp/ip timeout timer * NET_TIMER tcp/ip timeout timer
*
* MISC_TIMER reserved for special uses like the 387 timeouts etc
*/ */
#define BLANK_TIMER 0 #define BLANK_TIMER 0
...@@ -33,6 +35,7 @@ ...@@ -33,6 +35,7 @@
#define SCSI_TIMER 18 #define SCSI_TIMER 18
#define NET_TIMER 19 #define NET_TIMER 19
#define SOUND_TIMER 20 #define SOUND_TIMER 20
#define MISC_TIMER 21
struct timer_struct { struct timer_struct {
unsigned long expires; unsigned long expires;
......
...@@ -99,6 +99,7 @@ struct serial_struct { ...@@ -99,6 +99,7 @@ struct serial_struct {
#define ASYNC_HUP_NOTIFY 0x0001 /* Notify blocked open on hangups */ #define ASYNC_HUP_NOTIFY 0x0001 /* Notify blocked open on hangups */
#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ #define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
#define ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */ #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_MASK 0x0030
#define ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ #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 @@ ...@@ -18,6 +18,7 @@
#include <linux/head.h> #include <linux/head.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/timer.h>
extern unsigned long * prof_buffer; extern unsigned long * prof_buffer;
extern unsigned long prof_len; extern unsigned long prof_len;
...@@ -203,6 +204,17 @@ static void parse_options(char *line) ...@@ -203,6 +204,17 @@ static void parse_options(char *line)
envp_init[envs+1] = NULL; 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) void start_kernel(void)
{ {
/* /*
...@@ -266,13 +278,19 @@ void start_kernel(void) ...@@ -266,13 +278,19 @@ void start_kernel(void)
if (hard_math) { if (hard_math) {
unsigned short control_word; 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)); __asm__("fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
control_word &= 0xffc0; control_word &= 0xffc0;
__asm__("fldcw %0 ; fwait"::"m" (*&control_word)); __asm__("fldcw %0 ; fwait"::"m" (*&control_word));
outb_p(inb_p(0x21) | (1 << 2), 0x21); outb_p(inb_p(0x21) | (1 << 2), 0x21);
__asm__("fldz ; fld1 ; fdiv %st,%st(1) ; fwait"); __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(); move_to_user_mode();
if (!fork()) /* we count on this going ok */ if (!fork()) /* we count on this going ok */
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
SUBDIRS = scsi 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 all: blk_drv.a scsisubdirs
...@@ -38,6 +38,9 @@ dep: ...@@ -38,6 +38,9 @@ dep:
$(CPP) -M *.c > .depend $(CPP) -M *.c > .depend
for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep); done for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep); done
xd.o:
$(CC) $(CFLAGS) -fno-omit-frame-pointer $(RAMDISK) -c $<
dummy: dummy:
# #
......
...@@ -78,6 +78,8 @@ extern void rd_load(void); ...@@ -78,6 +78,8 @@ extern void rd_load(void);
extern long rd_init(long mem_start, int length); extern long rd_init(long mem_start, int length);
extern int ramdisk_size; extern int ramdisk_size;
extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end);
#define RO_IOCTLS(dev,where) \ #define RO_IOCTLS(dev,where) \
case BLKROSET: if (!suser()) return -EPERM; \ case BLKROSET: if (!suser()) return -EPERM; \
set_device_ro((dev),get_fs_long((long *) (where))); return 0; \ set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
...@@ -147,6 +149,14 @@ extern int ramdisk_size; ...@@ -147,6 +149,14 @@ extern int ramdisk_size;
#define DEVICE_ON(device) #define DEVICE_ON(device)
#define DEVICE_OFF(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 #else
/* unknown blk device */ /* unknown blk device */
#error "unknown blk device" #error "unknown blk device"
......
...@@ -385,6 +385,9 @@ long blk_dev_init(long mem_start, long mem_end) ...@@ -385,6 +385,9 @@ long blk_dev_init(long mem_start, long mem_end)
memset(ro_bits,0,sizeof(ro_bits)); memset(ro_bits,0,sizeof(ro_bits));
#ifdef CONFIG_BLK_DEV_HD #ifdef CONFIG_BLK_DEV_HD
mem_start = hd_init(mem_start,mem_end); mem_start = hd_init(mem_start,mem_end);
#endif
#ifdef CONFIG_BLK_DEV_XD
mem_start = xd_init(mem_start,mem_end);
#endif #endif
if (ramdisk_size) if (ramdisk_size)
mem_start += rd_init(mem_start, ramdisk_size*1024); mem_start += rd_init(mem_start, ramdisk_size*1024);
......
...@@ -91,8 +91,8 @@ struct config { ...@@ -91,8 +91,8 @@ struct config {
unsigned char interrupt: 4; unsigned char interrupt: 4;
unsigned char dma_channel: 3; unsigned char dma_channel: 3;
unsigned char bios_drive_number: 1; unsigned char bios_drive_number: 1;
unsigned char heads: 6; unsigned char heads;
unsigned char sectors: 6; unsigned char sectors;
unsigned char ha_scsi_id: 3; unsigned char ha_scsi_id: 3;
unsigned char subversion: 4; unsigned char subversion: 4;
}; };
......
This diff is collapsed.
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#define NPAR 16 #define NPAR 16
extern void vt_init(void); 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_columns; /* Number of text columns */
unsigned long video_num_lines; /* Number of test lines */ unsigned long video_num_lines; /* Number of test lines */
...@@ -1244,6 +1245,7 @@ long con_init(long kmem_start) ...@@ -1244,6 +1245,7 @@ long con_init(long kmem_start)
long base; long base;
int orig_x = ORIG_X; int orig_x = ORIG_X;
int orig_y = ORIG_Y; int orig_y = ORIG_Y;
void console_print(const char * b);
vc_scrmembuf = (unsigned short *) kmem_start; vc_scrmembuf = (unsigned short *) kmem_start;
video_num_columns = ORIG_VIDEO_COLS; video_num_columns = ORIG_VIDEO_COLS;
...@@ -1334,6 +1336,7 @@ long con_init(long kmem_start) ...@@ -1334,6 +1336,7 @@ long con_init(long kmem_start)
display_desc, display_desc,
video_num_columns,video_num_lines, video_num_columns,video_num_lines,
NR_CONSOLES); NR_CONSOLES);
register_console(console_print);
return kmem_start; return kmem_start;
} }
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
extern void do_keyboard_interrupt(void); extern void do_keyboard_interrupt(void);
extern void ctrl_alt_del(void); extern void ctrl_alt_del(void);
extern void change_console(unsigned int new_console); extern void change_console(unsigned int new_console);
extern void fake_keyboard_interrupt(void);
unsigned long kbd_flags = 0; unsigned long kbd_flags = 0;
unsigned long kbd_dead_keys = 0; unsigned long kbd_dead_keys = 0;
...@@ -75,23 +76,6 @@ static inline void kb_wait(void) ...@@ -75,23 +76,6 @@ static inline void kb_wait(void)
break; 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 void keyboard_interrupt(int int_pt_regs)
{ {
static unsigned char rep = 0xff; static unsigned char rep = 0xff;
...@@ -102,8 +86,11 @@ static void keyboard_interrupt(int int_pt_regs) ...@@ -102,8 +86,11 @@ static void keyboard_interrupt(int int_pt_regs)
if (!kbd_dead_keys) if (!kbd_dead_keys)
kbd_prev_dead_keys = 0; kbd_prev_dead_keys = 0;
kbd_dead_keys = 0; kbd_dead_keys = 0;
send_cmd(0xAD); kb_wait();
scancode = get_scancode(); if (!(inb_p(0x64) & 0x01))
goto end_kbd_intr;
scancode = inb(0x60);
mark_bh(KEYBOARD_BH);
if (scancode == 0xfa) { if (scancode == 0xfa) {
acknowledge = 1; acknowledge = 1;
goto end_kbd_intr; goto end_kbd_intr;
...@@ -145,8 +132,6 @@ static void keyboard_interrupt(int int_pt_regs) ...@@ -145,8 +132,6 @@ static void keyboard_interrupt(int int_pt_regs)
key_table[scancode](scancode); key_table[scancode](scancode);
rep = scancode; rep = scancode;
end_kbd_intr: end_kbd_intr:
send_cmd(0xAE);
mark_bh(KEYBOARD_BH);
} }
static void put_queue(int ch) static void put_queue(int ch)
...@@ -1116,13 +1101,15 @@ unsigned int handle_diacr(unsigned int ch) ...@@ -1116,13 +1101,15 @@ unsigned int handle_diacr(unsigned int ch)
{ {
static unsigned char diacr_table[] = static unsigned char diacr_table[] =
{'`', 180, '^', '~', 168, 0}; /* Must end with 0 */ {'`', 180, '^', '~', 168, 0}; /* Must end with 0 */
static unsigned char ret_diacr[] =
{'`', '\'', '^', '~', '"' }; /* Must not end with 0 */
int i; int i;
for(i=0; diacr_table[i]; i++) for(i=0; diacr_table[i]; i++)
if (ch==diacr_table[i] && ((1<<i)&kbd->kbd_flags)) { if (ch==diacr_table[i] && ((1<<i)&kbd->kbd_flags)) {
if (diacr == i) { if (diacr == i) {
diacr=-1; diacr=-1;
return ch; /* pressed twice */ return ret_diacr[i]; /* pressed twice */
} else { } else {
diacr=i; /* key is dead */ diacr=i; /* key is dead */
return 0; return 0;
...@@ -1131,7 +1118,7 @@ unsigned int handle_diacr(unsigned int ch) ...@@ -1131,7 +1118,7 @@ unsigned int handle_diacr(unsigned int ch)
if (diacr == -1) if (diacr == -1)
return ch; return ch;
else if (ch == ' ') { else if (ch == ' ') {
ch=diacr_table[diacr]; ch=ret_diacr[diacr];
diacr=-1; diacr=-1;
return ch; return ch;
} else if (ch<64 || ch>122) { } else if (ch<64 || ch>122) {
...@@ -1366,6 +1353,10 @@ static void kbd_bh(void * unused) ...@@ -1366,6 +1353,10 @@ static void kbd_bh(void * unused)
want_console = -1; want_console = -1;
} }
do_keyboard_interrupt(); do_keyboard_interrupt();
cli();
if (inb_p(0x64) & 0x01)
fake_keyboard_interrupt();
sti();
} }
long no_idt[2] = {0, 0}; long no_idt[2] = {0, 0};
...@@ -1475,6 +1466,6 @@ unsigned long kbd_init(unsigned long kmem_start) ...@@ -1475,6 +1466,6 @@ unsigned long kbd_init(unsigned long kmem_start)
} }
bh_base[KEYBOARD_BH].routine = kbd_bh; bh_base[KEYBOARD_BH].routine = kbd_bh;
request_irq(KEYBOARD_IRQ,keyboard_interrupt); request_irq(KEYBOARD_IRQ,keyboard_interrupt);
keyboard_interrupt(0); mark_bh(KEYBOARD_BH);
return kmem_start; return kmem_start;
} }
...@@ -299,6 +299,8 @@ static int lp_open(struct inode * inode, struct file * file) ...@@ -299,6 +299,8 @@ static int lp_open(struct inode * inode, struct file * file)
sa.sa_restorer = NULL; sa.sa_restorer = NULL;
ret = irqaction(irq, &sa); ret = irqaction(irq, &sa);
if (ret) { 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); printk("lp%d unable to use interrupt %d, error %d\n", irq, ret);
return ret; return ret;
} }
...@@ -317,6 +319,7 @@ static void lp_release(struct inode * inode, struct file * file) ...@@ -317,6 +319,7 @@ static void lp_release(struct inode * inode, struct file * file)
if ((irq = LP_IRQ(minor))) { if ((irq = LP_IRQ(minor))) {
free_irq(irq); free_irq(irq);
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
} }
LP_F(minor) &= ~LP_BUSY; LP_F(minor) &= ~LP_BUSY;
...@@ -353,28 +356,48 @@ static int lp_ioctl(struct inode *inode, struct file *file, ...@@ -353,28 +356,48 @@ static int lp_ioctl(struct inode *inode, struct file *file,
case LPSETIRQ: { case LPSETIRQ: {
int ret; int ret;
int oldirq; int oldirq;
int newirq = arg;
struct lp_struct *lp = &lp_table[minor];
struct sigaction sa; struct sigaction sa;
if (!suser()) if (!suser())
return -EPERM; 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); free_irq(oldirq);
} }
if (arg) { if (newirq) {
/* Install new irq */ /* Install new irq */
sa.sa_handler = lp_interrupt; sa.sa_handler = lp_interrupt;
sa.sa_flags = SA_INTERRUPT; sa.sa_flags = SA_INTERRUPT;
sa.sa_mask = 0; sa.sa_mask = 0;
sa.sa_restorer = NULL; sa.sa_restorer = NULL;
if ((ret = irqaction(arg, &sa))) { if ((ret = irqaction(newirq, &sa))) {
if (oldirq) if (oldirq) {
/* restore old irq */ /* restore old irq */
irqaction(oldirq, &sa); irqaction(oldirq, &sa);
} else {
/* We don't need the buffer */
kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
lp->lp_buffer = NULL;
}
return ret; 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); lp_reset(minor);
break; break;
} }
...@@ -405,8 +428,10 @@ long lp_init(long kmem_start) ...@@ -405,8 +428,10 @@ long lp_init(long kmem_start)
unsigned int testvalue = 0; unsigned int testvalue = 0;
int count = 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"); printk("unable to get major 6 for line printer\n");
return kmem_start;
}
/* take on all known port values */ /* take on all known port values */
for (offset = 0; offset < LP_NO; offset++) { for (offset = 0; offset < LP_NO; offset++) {
/* write to port & read back to check */ /* write to port & read back to check */
......
This diff is collapsed.
...@@ -1060,6 +1060,7 @@ static void release_dev(int dev, struct file * filp) ...@@ -1060,6 +1060,7 @@ static void release_dev(int dev, struct file * filp)
{ {
struct tty_struct *tty, *o_tty; struct tty_struct *tty, *o_tty;
struct termios *tp, *o_tp; struct termios *tp, *o_tp;
struct task_struct **p;
tty = tty_table[dev]; tty = tty_table[dev];
tp = tty_termios[dev]; tp = tty_termios[dev];
...@@ -1107,6 +1108,15 @@ static void release_dev(int dev, struct file * filp) ...@@ -1107,6 +1108,15 @@ static void release_dev(int dev, struct file * filp)
if (tty->count) if (tty->count)
return; 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) if (ldiscs[tty->disc].close != NULL)
ldiscs[tty->disc].close(tty); ldiscs[tty->disc].close(tty);
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
int sys_close(int fd); int sys_close(int fd);
int getrusage(struct task_struct *, int, struct rusage *); 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; return -EINVAL;
if (!priv && ((sig != SIGCONT) || (current->session != p->session)) && if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
(current->euid != p->euid) && (current->uid != p->uid) && !suser()) (current->euid != p->euid) && (current->uid != p->uid) && !suser())
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
/* /*
* 'fork.c' contains the help-routines for the 'fork' system call * '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 * 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()' * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
*/ */
...@@ -24,27 +24,6 @@ ...@@ -24,27 +24,6 @@
long last_pid=0; 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) static int find_empty_process(void)
{ {
int i, task_nr; int i, task_nr;
......
...@@ -125,6 +125,11 @@ static void (*bad_interrupt[16])(void) = { ...@@ -125,6 +125,11 @@ static void (*bad_interrupt[16])(void) = {
bad_IRQ14_interrupt, bad_IRQ15_interrupt bad_IRQ14_interrupt, bad_IRQ15_interrupt
}; };
void fake_keyboard_interrupt(void)
{
IRQ1_interrupt();
}
/* /*
* Initial irq handlers. * Initial irq handlers.
*/ */
......
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
* linux/kernel/printk.c * linux/kernel/printk.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * 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> #include <stdarg.h>
...@@ -18,46 +25,48 @@ static char buf[1024]; ...@@ -18,46 +25,48 @@ static char buf[1024];
extern int vsprintf(char * buf, const char * fmt, va_list args); extern int vsprintf(char * buf, const char * fmt, va_list args);
extern void console_print(const char *); 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 log_start = 0;
static unsigned long logged_chars = 0;
unsigned long log_size = 0; unsigned long log_size = 0;
int log_to_console = 1;
struct wait_queue * log_wait = NULL; 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) int sys_syslog(int type, char * buf, int len)
{ {
unsigned long i; unsigned long i, j, count;
int do_clear = 0;
char c; char c;
if (!suser()) if ((type != 3) && !suser())
return -EPERM; return -EPERM;
switch (type) { switch (type) {
case 0: case 0: /* Close log */
i = log_page;
log_page = 0;
free_page(i);
wake_up_interruptible(&log_wait);
return 0; return 0;
case 1: case 1: /* Open and reset log */
i = get_free_page(GFP_KERNEL); log_start += log_size;
if (log_page) { log_size = 0;
free_page(i); return 0;
return 0; case 2: /* Read from log */
} else if ((log_page = i) != 0) {
log_start = log_size = 0;
return 0;
}
return -ENOMEM;
case 2:
if (!buf || len < 0) if (!buf || len < 0)
return -EINVAL; return -EINVAL;
if (!len) if (!len)
return 0; return 0;
i = verify_area(VERIFY_WRITE, buf, len); verify_area(VERIFY_WRITE,buf,len);
if (i)
return i;
while (!log_size) { while (!log_size) {
if (!log_page)
return -EIO;
if (current->signal & ~current->blocked) if (current->signal & ~current->blocked)
return -ERESTARTSYS; return -ERESTARTSYS;
cli(); cli();
...@@ -67,7 +76,7 @@ int sys_syslog(int type, char * buf, int len) ...@@ -67,7 +76,7 @@ int sys_syslog(int type, char * buf, int len)
} }
i = 0; i = 0;
while (log_size && i < len) { while (log_size && i < len) {
c = *((char *) log_page+log_start); c = *((char *) log_buf+log_start);
log_start++; log_start++;
log_size--; log_size--;
log_start &= 4095; log_start &= 4095;
...@@ -76,6 +85,36 @@ int sys_syslog(int type, char * buf, int len) ...@@ -76,6 +85,36 @@ int sys_syslog(int type, char * buf, int len)
i++; i++;
} }
return 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; return -EINVAL;
} }
...@@ -85,21 +124,47 @@ int printk(const char *fmt, ...) ...@@ -85,21 +124,47 @@ int printk(const char *fmt, ...)
{ {
va_list args; va_list args;
int i,j; int i,j;
char * p;
va_start(args, fmt); va_start(args, fmt);
i=vsprintf(buf,fmt,args); i=vsprintf(buf,fmt,args);
va_end(args); va_end(args);
for (j = 0; j < i && log_page ; j++) { for (j = 0; j < i ; j++) {
p = (char *) log_page + (4095 & (log_start+log_size)); log_buf[(log_start+log_size) & 4095] = buf[j];
*p = buf[j];
if (log_size < 4096) if (log_size < 4096)
log_size++; log_size++;
else else
log_start++; log_start++;
logged_chars++;
} }
if (log_page) wake_up_interruptible(&log_wait);
wake_up_interruptible(&log_wait); if (log_to_console && console_print_proc)
console_print(buf); (*console_print_proc)(buf);
return i; 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) ...@@ -159,8 +159,10 @@ int sys_pause(void)
if (sa->sa_handler == SIG_IGN || (sa->sa_handler == SIG_DFL if (sa->sa_handler == SIG_IGN || (sa->sa_handler == SIG_DFL
&& (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))) && (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH)))
current->blocked |= mask; current->blocked |= mask;
current->state = TASK_INTERRUPTIBLE; do {
schedule(); current->state = TASK_INTERRUPTIBLE;
schedule();
} while (!(current->signal & ~current->blocked));
/* if a suspending signal interrupted us we must restart */ /* if a suspending signal interrupted us we must restart */
if (!(current->signal & ~current->blocked & if (!(current->signal & ~current->blocked &
~(_S(SIGSTOP) | _S(SIGTSTP) | _S(SIGTTIN) | _S(SIGTTOU)))) { ~(_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); ...@@ -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 * want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake. * mistake.
*/ */
int do_signal(long signr,struct pt_regs * regs) void do_signal(struct pt_regs * regs)
{ {
unsigned long signr;
unsigned long sa_handler; unsigned long sa_handler;
long old_eip = regs->eip; long old_eip = regs->eip;
struct sigaction * sa = current->sigaction + signr - 1; struct sigaction * sa;
int longs; int longs;
unsigned long * tmp_esp; unsigned long * tmp_esp;
sa_handler = (unsigned long) sa->sa_handler; if (regs->orig_eax >= 0 && regs->eax == -ERESTARTNOINTR) {
if ((regs->orig_eax >= 0) && regs->eax = regs->orig_eax;
((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) { regs->eip = old_eip -= 2;
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 (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 */ /* check for SIGCHLD: it's special */
if (signr == SIGCHLD) if (signr == SIGCHLD)
while (sys_waitpid(-1,NULL,WNOHANG) > 0) while (sys_waitpid(-1,NULL,WNOHANG) > 0)
/* nothing */; /* nothing */;
return(1); /* Ignore, see if there are more signals... */ continue;
} }
if (!sa_handler) { if (!sa_handler) {
if (current->pid == 1) if (current->pid == 1)
return 1; continue;
switch (signr) { switch (signr) {
case SIGCONT: case SIGCONT:
case SIGCHLD: case SIGCHLD:
case SIGWINCH: case SIGWINCH:
return(1); /* Ignore, ... */ continue;
case SIGSTOP: case SIGSTOP:
case SIGTSTP: case SIGTSTP:
case SIGTTIN: case SIGTTIN:
case SIGTTOU: case SIGTTOU:
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
current->exit_code = signr; current->exit_code = signr;
if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP)) SA_NOCLDSTOP))
send_sig(SIGCHLD, current->p_pptr, 1); send_sig(SIGCHLD, current->p_pptr, 1);
return(1); /* Reschedule another event */ schedule();
continue;
case SIGQUIT: case SIGQUIT:
case SIGILL: case SIGILL:
case SIGTRAP: case SIGTRAP:
case SIGIOT: case SIGIOT:
case SIGFPE: case SIGFPE:
case SIGSEGV: case SIGSEGV:
if (core_dump(signr,regs)) if (core_dump(signr,regs))
signr |= 0x80; signr |= 0x80;
/* fall through */ /* fall through */
default: default:
current->signal |= _S(signr & 0x7f); current->signal |= _S(signr & 0x7f);
do_exit(signr); do_exit(signr);
}
} }
} /*
/* * OK, we're invoking a handler
* OK, we're invoking a handler */
*/ if (regs->orig_eax >= 0 && regs->eax == -ERESTARTSYS) {
if (sa->sa_flags & SA_ONESHOT) if (sa->sa_flags & SA_INTERRUPT)
sa->sa_handler = NULL; regs->eax = -EINTR;
regs->eip = sa_handler; else {
longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4); regs->eax = regs->orig_eax;
regs->esp -= longs; regs->eip = old_eip -= 2;
tmp_esp = (unsigned long *) regs->esp; }
verify_area(VERIFY_WRITE,tmp_esp,longs); }
put_fs_long((long) sa->sa_restorer,tmp_esp++); if (sa->sa_flags & SA_ONESHOT)
put_fs_long(signr,tmp_esp++); sa->sa_handler = NULL;
if (!(sa->sa_flags & SA_NOMASK)) regs->eip = sa_handler;
put_fs_long(current->blocked,tmp_esp++); longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
put_fs_long(regs->eax,tmp_esp++); regs->esp -= longs;
put_fs_long(regs->ecx,tmp_esp++); tmp_esp = (unsigned long *) regs->esp;
put_fs_long(regs->edx,tmp_esp++); verify_area(VERIFY_WRITE,tmp_esp,longs);
put_fs_long(regs->eflags,tmp_esp++); put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(old_eip,tmp_esp++); put_fs_long(signr,tmp_esp++);
current->blocked |= sa->sa_mask; 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 */ /* force a supervisor-mode page-in of the signal handler to reduce races */
__asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler)); __asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler));
return(0); /* Continue, execute 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) ...@@ -130,7 +130,12 @@ int sys_prof(void)
return -ENOSYS; 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; unsigned long stack;
......
...@@ -65,23 +65,12 @@ VM_MASK = 0x00020000 ...@@ -65,23 +65,12 @@ VM_MASK = 0x00020000
/* /*
* these are offsets into the task-struct. * these are offsets into the task-struct.
*/ */
state = 0 state = 0
counter = 4 counter = 4
priority = 8 priority = 8
signal = 12 signal = 12
sigaction = 16 # MUST be 16 (=len of sigaction) blocked = 16
blocked = (33*16) flags = 20
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
ENOSYS = 38 ENOSYS = 38
...@@ -113,6 +102,21 @@ ENOSYS = 38 ...@@ -113,6 +102,21 @@ ENOSYS = 38
movl $0x17,%edx; \ movl $0x17,%edx; \
mov %dx,%fs 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 .align 4
reschedule: reschedule:
pushl $ret_from_sys_call pushl $ret_from_sys_call
...@@ -151,16 +155,16 @@ _system_call: ...@@ -151,16 +155,16 @@ _system_call:
ret_from_sys_call: ret_from_sys_call:
movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
testl $VM_MASK,%eax # different then testl $VM_MASK,%eax # different then
jne 4f jne 1f
cmpw $0x0f,CS(%esp) # was old code segment supervisor ? cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
jne 2f jne 2f
cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ? cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
jne 2f 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 orl $IF_MASK,%eax # these just try to make sure
andl $~NT_MASK,%eax # the program doesn't do anything andl $~NT_MASK,%eax # the program doesn't do anything
movl %eax,EFLAGS(%esp) # stupid movl %eax,EFLAGS(%esp) # stupid
1: cmpl $0,_need_resched cmpl $0,_need_resched
jne reschedule jne reschedule
movl _current,%eax movl _current,%eax
cmpl _task,%eax # task[0] cannot have signals cmpl _task,%eax # task[0] cannot have signals
...@@ -169,44 +173,28 @@ ret_from_sys_call: ...@@ -169,44 +173,28 @@ ret_from_sys_call:
jne reschedule jne reschedule
cmpl $0,counter(%eax) # counter cmpl $0,counter(%eax) # counter
je reschedule je reschedule
movl signal(%eax),%ebx
movl blocked(%eax),%ecx movl blocked(%eax),%ecx
notl %ecx notl %ecx
andl %ebx,%ecx andl signal(%eax),%ecx
je 2f # XXX - branch is almost always taken jne signal_return
bsfl %ecx,%ecx 2: RESTORE_ALL
btrl %ecx,signal(%eax) # change atomically (%ebx is stale) .align 4
jnc 2f # bit became clear (can't happen?) signal_return:
incl %ecx
movl %esp,%ebx movl %esp,%ebx
testl $VM_MASK,EFLAGS(%esp)
je 3f
pushl %ebx 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 call _save_v86_state
popl %ecx
movl %eax,%ebx
movl %eax,%esp movl %eax,%esp
3: pushl %ebx pushl %eax
pushl %ecx
call _do_signal call _do_signal
popl %ecx
popl %ebx popl %ebx
testl %eax, %eax RESTORE_ALL
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
.align 4 .align 4
_sys_execve: _sys_execve:
......
...@@ -563,10 +563,28 @@ void do_wp_page(unsigned long error_code, unsigned long address, ...@@ -563,10 +563,28 @@ void do_wp_page(unsigned long error_code, unsigned long address,
invalidate(); invalidate();
} }
void write_verify(unsigned long address) int verify_area(int type, void * addr, unsigned long size)
{ {
if (address < TASK_SIZE) unsigned long start;
do_wp_page(1,address,current,0);
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) static void get_empty_page(struct task_struct * tsk, unsigned long address)
......
...@@ -662,7 +662,7 @@ int sys_swapon(const char * specialfile) ...@@ -662,7 +662,7 @@ int sys_swapon(const char * specialfile)
p->flags = 0; p->flags = 0;
return -ENOMEM; return -ENOMEM;
} }
read_swap_page(type < 1,tmp); read_swap_page(SWP_ENTRY(type,0),tmp);
if (strncmp("SWAP-SPACE",tmp+4086,10)) { if (strncmp("SWAP-SPACE",tmp+4086,10)) {
printk("Unable to find swap-space signature\n"); printk("Unable to find swap-space signature\n");
free_page((long) tmp); free_page((long) tmp);
......
...@@ -317,40 +317,24 @@ arp_destroy(unsigned long paddr) ...@@ -317,40 +317,24 @@ arp_destroy(unsigned long paddr)
{ {
unsigned long hash; unsigned long hash;
struct arp_table *apt; struct arp_table *apt;
struct arp_table *lapt; struct arp_table **lapt;
PRINTK (("arp_destroy (paddr=%X)\n",paddr)); PRINTK (("arp_destroy (paddr=%X)\n",paddr));
/* we don't want to destroy are own arp */ /* we don't want to destroy are own arp */
if (my_ip_addr(paddr)) return; if (my_ip_addr(paddr)) return;
hash = net32(paddr) & (ARP_TABLE_SIZE - 1); hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
cli(); /* can't be interrupted. */ cli(); /* can't be interrupted. */
/* make sure there is something there. */ lapt = (struct arp_table **) &arp_table[hash];
if (arp_table[hash] == NULL) return; while ((apt = *lapt) != NULL) {
if (apt->ip == paddr)
/* check the first one. */ {
if (arp_table[hash]->ip == paddr) *lapt = (struct arp_table *) apt->next;
{ arp_free(apt, sizeof(*apt));
apt = (struct arp_table *)arp_table[hash]; sti();
arp_table[hash] = arp_table[hash]->next; return;
arp_free (apt, sizeof (*apt)); }
sti(); lapt = (struct arp_table **) &apt->next;
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;
}
}
sti(); sti();
} }
...@@ -410,7 +394,7 @@ arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ...@@ -410,7 +394,7 @@ arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
tbl->last_used = timer_seq; 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); kfree_skb (skb, FREE_READ);
return (0); return (0);
......
...@@ -192,7 +192,7 @@ int ...@@ -192,7 +192,7 @@ int
ip_addr_match (unsigned long addr1, unsigned long addr2) ip_addr_match (unsigned long addr1, unsigned long addr2)
{ {
int i; int i;
if (addr1 == addr2) return (1); if (addr1 == addr2) return (IS_MYADDR);
for (i = 0; i < 4; i++, addr1 >>= 8, addr2 >>= 8) for (i = 0; i < 4; i++, addr1 >>= 8, addr2 >>= 8)
{ {
if ((addr1 & 0xff) != (addr2 & 0xff)) if ((addr1 & 0xff) != (addr2 & 0xff))
...@@ -203,20 +203,22 @@ ip_addr_match (unsigned long addr1, unsigned long addr2) ...@@ -203,20 +203,22 @@ ip_addr_match (unsigned long addr1, unsigned long addr2)
{ {
return (0); return (0);
} }
return (1); return (IS_BROADCAST);
} }
} }
return (1); return (IS_MYADDR);
} }
int int
my_ip_addr(unsigned long addr) my_ip_addr(unsigned long addr)
{ {
int i; int i;
int result;
for (i = 0; i < MAX_IP_ADDRES; i++) for (i = 0; i < MAX_IP_ADDRES; i++)
{ {
if (ip_addr[i] == 0) return (0); 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); return (0);
} }
......
...@@ -156,6 +156,12 @@ extern int ip_ads; ...@@ -156,6 +156,12 @@ extern int ip_ads;
#define MY_IP_ADDR ip_addr[0] #define MY_IP_ADDR ip_addr[0]
int my_ip_addr(unsigned long); int my_ip_addr(unsigned long);
/*
* returned by my_ip_addr..
*/
#define IS_MYADDR 1
#define IS_BROADCAST 2
#include "eth.h" #include "eth.h"
void void
......
...@@ -94,7 +94,14 @@ int main(int argc, char ** argv) ...@@ -94,7 +94,14 @@ int main(int argc, char ** argv)
if ((argc < 4) || (argc > 5)) if ((argc < 4) || (argc > 5))
usage(); usage();
if (argc > 4) { 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)) { if (stat(argv[4], &sb)) {
perror(argv[4]); perror(argv[4]);
die("Couldn't stat root device."); 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