Commit 728d1c78 authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.15c

parent f938a5c8
VERSION = 0.99 VERSION = 0.99
PATCHLEVEL = 15 PATCHLEVEL = 15
ALPHA = b ALPHA = c
all: Version zImage all: Version zImage
......
...@@ -301,7 +301,7 @@ static void select_callback(unsigned long unused) ...@@ -301,7 +301,7 @@ static void select_callback(unsigned long unused)
static void floppy_select(unsigned int nr) static void floppy_select(unsigned int nr)
{ {
static struct timer_list select = { NULL, 0, 0, select_callback }; static struct timer_list select = { NULL, NULL, 0, 0, select_callback };
if (current_drive == (current_DOR & 3)) { if (current_drive == (current_DOR & 3)) {
floppy_ready(); floppy_ready();
...@@ -324,10 +324,10 @@ static void motor_on_callback(unsigned long nr) ...@@ -324,10 +324,10 @@ static void motor_on_callback(unsigned long nr)
} }
static struct timer_list motor_on_timer[4] = { static struct timer_list motor_on_timer[4] = {
{ NULL, 0, 0, motor_on_callback }, { NULL, NULL, 0, 0, motor_on_callback },
{ NULL, 0, 1, motor_on_callback }, { NULL, NULL, 0, 1, motor_on_callback },
{ NULL, 0, 2, motor_on_callback }, { NULL, NULL, 0, 2, motor_on_callback },
{ NULL, 0, 3, motor_on_callback } { NULL, NULL, 0, 3, motor_on_callback }
}; };
static void motor_off_callback(unsigned long nr) static void motor_off_callback(unsigned long nr)
...@@ -341,10 +341,10 @@ static void motor_off_callback(unsigned long nr) ...@@ -341,10 +341,10 @@ static void motor_off_callback(unsigned long nr)
} }
static struct timer_list motor_off_timer[4] = { static struct timer_list motor_off_timer[4] = {
{ NULL, 0, 0, motor_off_callback }, { NULL, NULL, 0, 0, motor_off_callback },
{ NULL, 0, 1, motor_off_callback }, { NULL, NULL, 0, 1, motor_off_callback },
{ NULL, 0, 2, motor_off_callback }, { NULL, NULL, 0, 2, motor_off_callback },
{ NULL, 0, 3, motor_off_callback } { NULL, NULL, 0, 3, motor_off_callback }
}; };
static void floppy_on(unsigned int nr) static void floppy_on(unsigned int nr)
......
...@@ -60,6 +60,7 @@ static XD_SIGNATURE xd_sigs[] = { ...@@ -60,6 +60,7 @@ static XD_SIGNATURE xd_sigs[] = {
{ 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */ { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
{ 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */ { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
{ 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */ { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
{ 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
}; };
static u_char *xd_bases[] = static u_char *xd_bases[] =
{ {
...@@ -580,6 +581,34 @@ static void xd_seagate_init_drive (u_char drive) ...@@ -580,6 +581,34 @@ static void xd_seagate_init_drive (u_char drive)
printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive); printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);
} }
/* Omti support courtesy Dirk Melchers */
static void xd_omti_init_controller (u_char *address)
{
switch ((u_long) address) {
case 0xC8000: xd_iobase = 0x320; break;
case 0xD0000: xd_iobase = 0x324; break;
case 0xD8000: xd_iobase = 0x328; break;
case 0xE0000: xd_iobase = 0x32C; break;
default: printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);
xd_iobase = 0x320; break;
}
xd_irq = 5; /* the IRQ and DMA channel are fixed on the Omti controllers */
xd_dma = 3;
xd_maxsectors = 0x40;
outb(0,XD_RESET); /* reset the controller */
}
static void xd_omti_init_drive (u_char drive)
{
/* gets infos from drive */
xd_override_init_drive(drive);
/* set other parameters, Hardcoded, not that nice :-) */
xd_info[drive].control = 2;
}
/* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */ etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
static void xd_override_init_drive (u_char drive) static void xd_override_init_drive (u_char drive)
......
...@@ -34,7 +34,11 @@ ...@@ -34,7 +34,11 @@
#endif #endif
#ifndef KBD_DEFLEDS #ifndef KBD_DEFLEDS
#define KBD_DEFLEDS (1 << VC_NUMLOCK) /*
* Some laptops take the 789uiojklm,. keys as number pad when NumLock
* is on. This seems a good reason to start with NumLock off.
*/
#define KBD_DEFLEDS 0
#endif #endif
#ifndef KBD_DEFLOCK #ifndef KBD_DEFLOCK
......
...@@ -523,6 +523,9 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -523,6 +523,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
case TIOCSTI: case TIOCSTI:
if ((current->tty != dev) && !suser()) if ((current->tty != dev) && !suser())
return -EACCES; return -EACCES;
retval = verify_area(VERIFY_READ, (void *) arg, 1);
if (retval)
return retval;
put_tty_queue(get_fs_byte((char *) arg), &tty->read_q); put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
TTY_READ_FLUSH(tty); TTY_READ_FLUSH(tty);
return 0; return 0;
......
...@@ -86,7 +86,7 @@ kd_nosound(unsigned long ignored) ...@@ -86,7 +86,7 @@ kd_nosound(unsigned long ignored)
void void
kd_mksound(unsigned int count, unsigned int ticks) kd_mksound(unsigned int count, unsigned int ticks)
{ {
static struct timer_list sound_timer = { NULL, 0, 0, kd_nosound }; static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
cli(); cli();
del_timer(&sound_timer); del_timer(&sound_timer);
......
...@@ -377,7 +377,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -377,7 +377,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
return 0; return 0;
if (el3_debug > 4) { if (el3_debug > 4) {
printk("%s: el3_start_xmit(lenght = %d) called, status %4.4x.\n", printk("%s: el3_start_xmit(lenght = %ld) called, status %4.4x.\n",
dev->name, skb->len, inw(ioaddr + EL3_STATUS)); dev->name, skb->len, inw(ioaddr + EL3_STATUS));
} }
#ifndef final_version #ifndef final_version
......
...@@ -127,10 +127,12 @@ static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0}; ...@@ -127,10 +127,12 @@ static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
static struct blist blacklist[] = static struct blist blacklist[] =
{ {
{"DENON","DRD-25X","V"}, /* A cdrom that locks up when probed at lun != 0 */ {"DENON","DRD-25X","V"}, /* A cdrom that locks up when probed at lun != 0 */
{"MAXTOR","XT-3280","PR02"}, /* Locks-up when LUN>0 polled. */
{"MAXTOR","XT-4380S","B3C"}, /* Locks-up when LUN>0 polled. */ {"MAXTOR","XT-4380S","B3C"}, /* Locks-up when LUN>0 polled. */
{"MAXTOR","MXT-1240S","I1.2"}, /* Locks up when LUN > 0 polled */ {"MAXTOR","MXT-1240S","I1.2"}, /* Locks up when LUN > 0 polled */
{"MAXTOR","XT-4170S","B5A"}, /* Locks-up sometimes when LUN>0 polled. */ {"MAXTOR","XT-4170S","B5A"}, /* Locks-up sometimes when LUN>0 polled. */
{"NEC","CD-ROM DRIVE:841","1.0"}, /* Locks-up when LUN>0 polled. */ {"NEC","CD-ROM DRIVE:841","1.0"}, /* Locks-up when LUN>0 polled. */
{"RODIME","RO3000S","2.33"}, /* Locks up if polled for lun != 0 */
{"SEAGATE", "ST157N", "\004|j"}, /* causes failed REQUEST SENSE on lun 1 for aha152x {"SEAGATE", "ST157N", "\004|j"}, /* causes failed REQUEST SENSE on lun 1 for aha152x
* controller, which causes SCSI code to reset bus.*/ * controller, which causes SCSI code to reset bus.*/
{"SEAGATE", "ST296","921"}, /* Responds to all lun */ {"SEAGATE", "ST296","921"}, /* Responds to all lun */
...@@ -387,7 +389,7 @@ static void scan_scsis (void) ...@@ -387,7 +389,7 @@ static void scan_scsis (void)
scsi_devices[NR_SCSI_DEVICES].tagged_queue = 0; scsi_devices[NR_SCSI_DEVICES].tagged_queue = 0;
if ((scsi_devices[NR_SCSI_DEVICES].scsi_level == SCSI_2) && if ((scsi_devices[NR_SCSI_DEVICES].scsi_level >= SCSI_2) &&
(scsi_result[7] & 2)) { (scsi_result[7] & 2)) {
scsi_devices[NR_SCSI_DEVICES].tagged_supported = 1; scsi_devices[NR_SCSI_DEVICES].tagged_supported = 1;
scsi_devices[NR_SCSI_DEVICES].current_tag = 0; scsi_devices[NR_SCSI_DEVICES].current_tag = 0;
...@@ -451,6 +453,9 @@ static void scan_scsis (void) ...@@ -451,6 +453,9 @@ static void scan_scsis (void)
/* Some scsi devices cannot be polled for lun != 0 /* Some scsi devices cannot be polled for lun != 0
due to firmware bugs */ due to firmware bugs */
if(blacklisted(scsi_result)) break; if(blacklisted(scsi_result)) break;
/* Old drives like the MAXTOR XT-3280 say vers=0 */
if ((scsi_result[2] & 0x07) == 0)
break;
/* Some scsi-1 peripherals do not handle lun != 0. /* Some scsi-1 peripherals do not handle lun != 0.
I am assuming that scsi-2 peripherals do better */ I am assuming that scsi-2 peripherals do better */
if((scsi_result[2] & 0x07) == 1 && if((scsi_result[2] & 0x07) == 1 &&
......
...@@ -140,7 +140,7 @@ struct snd_wait { ...@@ -140,7 +140,7 @@ struct snd_wait {
#define DEFINE_TIMER(name, proc) \ #define DEFINE_TIMER(name, proc) \
static struct timer_list name = \ static struct timer_list name = \
{NULL, 0, 0, proc} {NULL, NULL, 0, 0, proc}
/* /*
* The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks. * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
......
...@@ -363,11 +363,9 @@ int ext2_new_block (struct super_block * sb, unsigned long goal, ...@@ -363,11 +363,9 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
/* /*
* First, test whether the goal block is free. * First, test whether the goal block is free.
*/ */
i = ((goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb)); if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
if (i >= EXT2_BLOCKS_PER_GROUP(sb) || i < 0) {
i = 0;
goal = es->s_first_data_block; goal = es->s_first_data_block;
} i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
gdp = get_group_desc (sb, i, &bh2); gdp = get_group_desc (sb, i, &bh2);
if (gdp->bg_free_blocks_count > 0) { if (gdp->bg_free_blocks_count > 0) {
j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb)); j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
......
...@@ -653,15 +653,13 @@ int ext2_rmdir (struct inode * dir, const char * name, int len) ...@@ -653,15 +653,13 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
retval = -ENOTDIR; retval = -ENOTDIR;
goto end_rmdir; goto end_rmdir;
} }
if (!empty_dir (inode)) { down(&inode->i_sem);
if (!empty_dir (inode))
retval = -ENOTEMPTY; retval = -ENOTEMPTY;
goto end_rmdir; else if (de->inode != inode->i_ino)
}
if (de->inode != inode->i_ino) {
retval = -ENOENT; retval = -ENOENT;
goto end_rmdir; else {
} if (inode->i_count > 1) {
if (inode->i_count > 1) {
/* /*
* Are we deleting the last instance of a busy directory? * Are we deleting the last instance of a busy directory?
* Better clean up if so. * Better clean up if so.
...@@ -669,9 +667,11 @@ int ext2_rmdir (struct inode * dir, const char * name, int len) ...@@ -669,9 +667,11 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
* Make directory empty (it will be truncated when finally * Make directory empty (it will be truncated when finally
* dereferenced). This also inhibits ext2_add_entry. * dereferenced). This also inhibits ext2_add_entry.
*/ */
inode->i_size = 0; inode->i_size = 0;
}
retval = ext2_delete_entry (de, bh);
} }
retval = ext2_delete_entry (de, bh); up(&inode->i_sem);
if (retval) if (retval)
goto end_rmdir; goto end_rmdir;
bh->b_dirt = 1; bh->b_dirt = 1;
......
...@@ -124,7 +124,7 @@ typedef void nonconst; ...@@ -124,7 +124,7 @@ typedef void nonconst;
static void hpfs_read_inode(struct inode *); static void hpfs_read_inode(struct inode *);
static void hpfs_put_super(struct super_block *); static void hpfs_put_super(struct super_block *);
static void hpfs_statfs(struct super_block *, struct statfs *); static void hpfs_statfs(struct super_block *, struct statfs *);
static int hpfs_remount_fs(struct super_block *, int *); static int hpfs_remount_fs(struct super_block *, int *, char *);
static const struct super_operations hpfs_sops = static const struct super_operations hpfs_sops =
{ {
...@@ -752,7 +752,7 @@ static void hpfs_statfs(struct super_block *s, struct statfs *buf) ...@@ -752,7 +752,7 @@ static void hpfs_statfs(struct super_block *s, struct statfs *buf)
* remount. Don't let read only be turned off. * remount. Don't let read only be turned off.
*/ */
static int hpfs_remount_fs(struct super_block *s, int *flags) static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
{ {
if (!(*flags & MS_RDONLY)) if (!(*flags & MS_RDONLY))
return -EINVAL; return -EINVAL;
......
...@@ -384,6 +384,7 @@ struct inode * get_empty_inode(void) ...@@ -384,6 +384,7 @@ struct inode * get_empty_inode(void)
clear_inode(inode); clear_inode(inode);
inode->i_count = 1; inode->i_count = 1;
inode->i_nlink = 1; inode->i_nlink = 1;
inode->i_sem.count = 1;
nr_free_inodes--; nr_free_inodes--;
if (nr_free_inodes < 0) { if (nr_free_inodes < 0) {
printk ("VFS: get_empty_inode: bad free inode count.\n"); printk ("VFS: get_empty_inode: bad free inode count.\n");
......
...@@ -275,7 +275,7 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -275,7 +275,7 @@ int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode, struct inode * base) struct inode ** res_inode, struct inode * base)
{ {
const char * basename; const char * basename;
int namelen,error,i; int namelen,error;
struct inode * dir, *inode; struct inode * dir, *inode;
struct task_struct ** p; struct task_struct ** p;
...@@ -297,43 +297,35 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -297,43 +297,35 @@ int open_namei(const char * pathname, int flag, int mode,
*res_inode=dir; *res_inode=dir;
return 0; return 0;
} }
for (i = 0; i < 5; i++) { /* races... */ dir->i_count++; /* lookup eats the dir */
dir->i_count++; /* lookup eats the dir */ if (flag & O_CREAT) {
down(&dir->i_sem);
error = lookup(dir,basename,namelen,&inode); error = lookup(dir,basename,namelen,&inode);
if (!error) if (!error) {
break; if (flag & O_EXCL) {
if (!(flag & O_CREAT)) { iput(inode);
iput(dir); error = -EEXIST;
return error; }
} } else if (!permission(dir,MAY_WRITE | MAY_EXEC))
if (!permission(dir,MAY_WRITE | MAY_EXEC)) { error = -EACCES;
iput(dir); else if (!dir->i_op || !dir->i_op->create)
return -EACCES; error = -EACCES;
} else if (IS_RDONLY(dir))
if (!dir->i_op || !dir->i_op->create) { error = -EROFS;
iput(dir); else {
return -EACCES; dir->i_count++; /* create eats the dir */
} error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
if (IS_RDONLY(dir)) { up(&dir->i_sem);
iput(dir);
return -EROFS;
}
dir->i_count++; /* create eats the dir */
error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
if (error != -EEXIST) {
iput(dir); iput(dir);
return error; return error;
} }
} up(&dir->i_sem);
} else
error = lookup(dir,basename,namelen,&inode);
if (error) { if (error) {
iput(dir); iput(dir);
return error; return error;
} }
if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
iput(dir);
iput(inode);
return -EEXIST;
}
error = follow_link(dir,inode,flag,mode,&inode); error = follow_link(dir,inode,flag,mode,&inode);
if (error) if (error)
return error; return error;
...@@ -415,7 +407,10 @@ int do_mknod(const char * filename, int mode, dev_t dev) ...@@ -415,7 +407,10 @@ int do_mknod(const char * filename, int mode, dev_t dev)
iput(dir); iput(dir);
return -EPERM; return -EPERM;
} }
return dir->i_op->mknod(dir,basename,namelen,mode,dev); down(&dir->i_sem);
error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
up(&dir->i_sem);
return error;
} }
asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev) asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev)
...@@ -467,7 +462,10 @@ static int do_mkdir(const char * pathname, int mode) ...@@ -467,7 +462,10 @@ static int do_mkdir(const char * pathname, int mode)
iput(dir); iput(dir);
return -EPERM; return -EPERM;
} }
return dir->i_op->mkdir(dir,basename,namelen,mode); down(&dir->i_sem);
error = dir->i_op->mkdir(dir,basename,namelen,mode);
up(&dir->i_sem);
return error;
} }
asmlinkage int sys_mkdir(const char * pathname, int mode) asmlinkage int sys_mkdir(const char * pathname, int mode)
...@@ -590,7 +588,10 @@ static int do_symlink(const char * oldname, const char * newname) ...@@ -590,7 +588,10 @@ static int do_symlink(const char * oldname, const char * newname)
iput(dir); iput(dir);
return -EPERM; return -EPERM;
} }
return dir->i_op->symlink(dir,basename,namelen,oldname); down(&dir->i_sem);
error = dir->i_op->symlink(dir,basename,namelen,oldname);
up(&dir->i_sem);
return error;
} }
asmlinkage int sys_symlink(const char * oldname, const char * newname) asmlinkage int sys_symlink(const char * oldname, const char * newname)
...@@ -646,7 +647,10 @@ static int do_link(struct inode * oldinode, const char * newname) ...@@ -646,7 +647,10 @@ static int do_link(struct inode * oldinode, const char * newname)
iput(oldinode); iput(oldinode);
return -EPERM; return -EPERM;
} }
return dir->i_op->link(oldinode, dir, basename, namelen); down(&dir->i_sem);
error = dir->i_op->link(oldinode, dir, basename, namelen);
up(&dir->i_sem);
return error;
} }
asmlinkage int sys_link(const char * oldname, const char * newname) asmlinkage int sys_link(const char * oldname, const char * newname)
...@@ -719,8 +723,11 @@ static int do_rename(const char * oldname, const char * newname) ...@@ -719,8 +723,11 @@ static int do_rename(const char * oldname, const char * newname)
iput(new_dir); iput(new_dir);
return -EPERM; return -EPERM;
} }
return old_dir->i_op->rename(old_dir, old_base, old_len, down(&new_dir->i_sem);
error = old_dir->i_op->rename(old_dir, old_base, old_len,
new_dir, new_base, new_len); new_dir, new_base, new_len);
up(&new_dir->i_sem);
return error;
} }
asmlinkage int sys_rename(const char * oldname, const char * newname) asmlinkage int sys_rename(const char * oldname, const char * newname)
......
...@@ -441,7 +441,7 @@ static int get_maps(int pid, char *buf) ...@@ -441,7 +441,7 @@ static int get_maps(int pid, char *buf)
return sz; return sz;
} }
asmlinkage int get_module_list( char *); extern int get_module_list(char *);
static int array_read(struct inode * inode, struct file * file,char * buf, int count) static int array_read(struct inode * inode, struct file * file,char * buf, int count)
{ {
......
...@@ -89,7 +89,7 @@ extern __inline__ int clear_bit(int nr, int * addr) ...@@ -89,7 +89,7 @@ extern __inline__ int clear_bit(int nr, int * addr)
addr += nr >> 5; addr += nr >> 5;
mask = 1 << (nr & 0x1f); mask = 1 << (nr & 0x1f);
cli(); cli();
retval = (mask & *addr) == 0; retval = (mask & *addr) != 0;
*addr &= ~mask; *addr &= ~mask;
sti(); sti();
return retval; return retval;
......
...@@ -171,6 +171,7 @@ struct inode { ...@@ -171,6 +171,7 @@ struct inode {
time_t i_ctime; time_t i_ctime;
unsigned long i_blksize; unsigned long i_blksize;
unsigned long i_blocks; unsigned long i_blocks;
struct semaphore i_sem;
struct inode_operations * i_op; struct inode_operations * i_op;
struct super_block * i_sb; struct super_block * i_sb;
struct wait_queue * i_wait; struct wait_queue * i_wait;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
/* IEEE 802.3 Ethernet magic constants. */ /* IEEE 802.3 Ethernet magic constants. */
#define ETH_ALEN 6 /* #bytes in eth addr */ #define ETH_ALEN 6 /* #bytes in eth addr */
#define ETH_HLEN 14 /* #bytes in eth header */ #define ETH_HLEN 14 /* #bytes in eth header */
#define ETH_ZLEN 64 /* min #bytes in frame */ #define ETH_ZLEN 60 /* min #bytes in frame */
#define ETH_FLEN 1536 /* max #bytes in frame */ #define ETH_FLEN 1536 /* max #bytes in frame */
#define ETH_DLEN (ETH_FLEN - ETH_HLEN) /* max #bytes of data */ #define ETH_DLEN (ETH_FLEN - ETH_HLEN) /* max #bytes of data */
......
...@@ -21,21 +21,32 @@ ...@@ -21,21 +21,32 @@
#include <linux/if.h> #include <linux/if.h>
/* This structure gets passed by the SIOCADDRTOLD and SIOCDELRTOLD calls. */
struct old_rtentry {
unsigned long rt_genmask;
struct sockaddr rt_dst;
struct sockaddr rt_gateway;
short rt_flags;
short rt_refcnt;
unsigned long rt_use;
char *rt_dev;
};
/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ /* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
struct rtentry { struct rtentry {
unsigned long rt_hash; /* hash key for lookups */ unsigned long rt_hash; /* hash key for lookups */
#define rt_genmask rt_hash struct sockaddr rt_dst; /* target address */
struct sockaddr rt_dst; struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
struct sockaddr rt_gateway; struct sockaddr rt_genmask; /* target network mask (IP) */
short rt_flags; short rt_flags;
short rt_refcnt; short rt_refcnt;
unsigned long rt_use; unsigned long rt_use;
#ifdef BSD_COMPATIBLE struct ifnet *rt_ifp;
struct ifnet *rt_ifp; short rt_metric; /* +1 for binary compatibility! */
#else char *rt_dev; /* forcing the device at add */
void *rt_dev;
#endif
}; };
#define RTF_UP 0x0001 /* route useable */ #define RTF_UP 0x0001 /* route useable */
#define RTF_GATEWAY 0x0002 /* destination is a gateway */ #define RTF_GATEWAY 0x0002 /* destination is a gateway */
#define RTF_HOST 0x0004 /* host entry (net otherwise) */ #define RTF_HOST 0x0004 /* host entry (net otherwise) */
......
...@@ -479,6 +479,21 @@ extern inline void select_wait(struct wait_queue ** wait_address, select_table * ...@@ -479,6 +479,21 @@ extern inline void select_wait(struct wait_queue ** wait_address, select_table *
p->nr++; p->nr++;
} }
extern void __down(struct semaphore * sem);
extern inline void down(struct semaphore * sem)
{
if (sem->count <= 0)
__down(sem);
sem->count--;
}
extern inline void up(struct semaphore * sem)
{
sem->count++;
wake_up(&sem->wait);
}
static inline unsigned long _get_base(char * addr) static inline unsigned long _get_base(char * addr)
{ {
unsigned long __base; unsigned long __base;
......
...@@ -39,6 +39,10 @@ struct ip_config { ...@@ -39,6 +39,10 @@ struct ip_config {
#define SIOCGPGRP 0x8904 #define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905 #define SIOCATMARK 0x8905
/* Routing table calls. */
#define SIOCADDRT 0x890B /* add routing table entry */
#define SIOCDELRT 0x890C /* delete routing table entry */
/* Socket configuration controls. */ /* Socket configuration controls. */
#define SIOCGIFNAME 0x8910 /* get iface name */ #define SIOCGIFNAME 0x8910 /* get iface name */
#define SIOCSIFLINK 0x8911 /* set iface channel */ #define SIOCSIFLINK 0x8911 /* set iface channel */
...@@ -64,9 +68,9 @@ struct ip_config { ...@@ -64,9 +68,9 @@ struct ip_config {
#define SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */ #define SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */
#define SIOCSIFENCAP 0x8926 #define SIOCSIFENCAP 0x8926
/* Routing table calls. */ /* Routing table calls (oldrtent - don't use) */
#define SIOCADDRT 0x8940 /* add routing table entry */ #define SIOCADDRTOLD 0x8940 /* add routing table entry */
#define SIOCDELRT 0x8941 /* delete routing table entry */ #define SIOCDELRTOLD 0x8941 /* delete routing table entry */
/* ARP cache control calls. */ /* ARP cache control calls. */
#define SIOCDARP 0x8950 /* delete ARP table entry */ #define SIOCDARP 0x8950 /* delete ARP table entry */
......
...@@ -75,6 +75,7 @@ extern struct timer_struct timer_table[32]; ...@@ -75,6 +75,7 @@ extern struct timer_struct timer_table[32];
*/ */
struct timer_list { struct timer_list {
struct timer_list *next; struct timer_list *next;
struct timer_list *prev;
unsigned long expires; unsigned long expires;
unsigned long data; unsigned long data;
void (*function)(unsigned long); void (*function)(unsigned long);
......
...@@ -11,6 +11,13 @@ struct wait_queue { ...@@ -11,6 +11,13 @@ struct wait_queue {
struct wait_queue * next; struct wait_queue * next;
}; };
struct semaphore {
int count;
struct wait_queue * wait;
};
#define MUTEX ((struct semaphore) { 1, NULL })
struct select_table_entry { struct select_table_entry {
struct wait_queue wait; struct wait_queue wait;
struct wait_queue ** wait_address; struct wait_queue ** wait_address;
......
...@@ -131,6 +131,8 @@ static void xd_wd_init_controller (u_char *address); ...@@ -131,6 +131,8 @@ static void xd_wd_init_controller (u_char *address);
static void xd_wd_init_drive (u_char drive); static void xd_wd_init_drive (u_char drive);
static void xd_seagate_init_controller (u_char *address); static void xd_seagate_init_controller (u_char *address);
static void xd_seagate_init_drive (u_char drive); static void xd_seagate_init_drive (u_char drive);
static void xd_omti_init_controller (u_char *address);
static void xd_omti_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); 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);
static void xd_override_init_drive (u_char drive); static void xd_override_init_drive (u_char drive);
......
...@@ -233,8 +233,7 @@ free_modules( void) ...@@ -233,8 +233,7 @@ free_modules( void)
/* /*
* Called by the /proc file system to return a current list of modules. * Called by the /proc file system to return a current list of modules.
*/ */
int int get_module_list(char *buf)
get_module_list( char *buf)
{ {
char *p; char *p;
char *q; char *q;
......
...@@ -361,6 +361,19 @@ void wake_up_interruptible(struct wait_queue **q) ...@@ -361,6 +361,19 @@ void wake_up_interruptible(struct wait_queue **q)
} while (tmp != *q); } while (tmp != *q);
} }
void __down(struct semaphore * sem)
{
struct wait_queue wait = { current, NULL };
add_wait_queue(&sem->wait, &wait);
current->state = TASK_UNINTERRUPTIBLE;
while (sem->count <= 0) {
schedule();
current->state = TASK_UNINTERRUPTIBLE;
}
current->state = TASK_RUNNING;
remove_wait_queue(&sem->wait, &wait);
}
static inline void __sleep_on(struct wait_queue **p, int state) static inline void __sleep_on(struct wait_queue **p, int state)
{ {
unsigned long flags; unsigned long flags;
......
...@@ -211,30 +211,34 @@ asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); ...@@ -211,30 +211,34 @@ asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
*/ */
asmlinkage int sys_sigreturn(unsigned long __unused) asmlinkage int sys_sigreturn(unsigned long __unused)
{ {
#define CHECK_SEG(x) if (x) x |= 3
#define COPY(x) regs->x = context.x #define COPY(x) regs->x = context.x
#define COPY_SEG(x) \
if ((context.x & 0xfffc) && (context.x & 3) != 3) goto badframe; COPY(x);
#define COPY_SEG_STRICT(x) \
if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
struct sigcontext_struct context; struct sigcontext_struct context;
struct pt_regs * regs; struct pt_regs * regs;
regs = (struct pt_regs *) &__unused; regs = (struct pt_regs *) &__unused;
if (verify_area(VERIFY_READ, (void *) regs->esp, sizeof(context)))
goto badframe;
memcpy_fromfs(&context,(void *) regs->esp, sizeof(context)); memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
current->blocked = context.oldmask & _BLOCKABLE; current->blocked = context.oldmask & _BLOCKABLE;
CHECK_SEG(context.ss); COPY_SEG(ds);
CHECK_SEG(context.cs); COPY_SEG(es);
CHECK_SEG(context.ds); COPY_SEG(fs);
CHECK_SEG(context.es); COPY_SEG(gs);
CHECK_SEG(context.fs); COPY_SEG_STRICT(ss);
CHECK_SEG(context.gs); COPY_SEG_STRICT(cs);
COPY(eip); COPY(eflags); COPY(eip); COPY(eflags);
COPY(ecx); COPY(edx); COPY(ecx); COPY(edx);
COPY(ebx); COPY(ebx);
COPY(esp); COPY(ebp); COPY(esp); COPY(ebp);
COPY(edi); COPY(esi); COPY(edi); COPY(esi);
COPY(cs); COPY(ss);
COPY(ds); COPY(es);
COPY(fs); COPY(gs);
regs->orig_eax = -1; /* disable syscall checks */ regs->orig_eax = -1; /* disable syscall checks */
return context.eax; return context.eax;
badframe:
do_exit(SIGSEGV);
} }
/* /*
......
...@@ -89,7 +89,7 @@ asmlinkage void alignment_check(void); ...@@ -89,7 +89,7 @@ asmlinkage void alignment_check(void);
printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx); regs->eax, regs->ebx, regs->ecx, regs->edx);
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08x\n", printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, regs->esp); regs->esi, regs->edi, regs->ebp, regs->esp);
printk("ds: %04x es: %04x fs: %04x gs: %04x\n", printk("ds: %04x es: %04x fs: %04x gs: %04x\n",
regs->ds, regs->es, regs->fs, regs->gs); regs->ds, regs->es, regs->fs, regs->gs);
...@@ -98,9 +98,11 @@ asmlinkage void alignment_check(void); ...@@ -98,9 +98,11 @@ asmlinkage void alignment_check(void);
for(i=0;i<20;i++) for(i=0;i<20;i++)
printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip))); printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
printk("\n"); printk("\n");
#if 0
for(i=0;i<5;i++) for(i=0;i<5;i++)
printk("%08x ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp))); printk("%08lx ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp)));
printk("\n"); printk("\n");
#endif
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
* Dominik Kubla : Better checking * Dominik Kubla : Better checking
* Tegge : Assorted corrections on cross port stuff * Tegge : Assorted corrections on cross port stuff
* Alan Cox : ATF_PERM was backwards! - might be useful now (sigh) * Alan Cox : ATF_PERM was backwards! - might be useful now (sigh)
* Alan Cox : Arp timer added.
* *
* To Fix: * To Fix:
* : arp response allocates an skbuff to send. However there is a perfectly * : arp response allocates an skbuff to send. However there is a perfectly
...@@ -60,6 +61,7 @@ ...@@ -60,6 +61,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/timer.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/in.h> #include <linux/in.h>
...@@ -250,6 +252,28 @@ arp_send_q(void) ...@@ -250,6 +252,28 @@ arp_send_q(void)
} }
static struct timer_list arp_timer;
static void arp_queue_ticker(unsigned long data);
static void arp_queue_kick(void)
{
arp_timer.expires = 500; /* 5 seconds */
arp_timer.data = 0;
arp_timer.function = arp_queue_ticker;
del_timer(&arp_timer);
add_timer(&arp_timer);
}
static void arp_queue_ticker(unsigned long data/*UNUSED*/)
{
arp_send_q();
if (skb_peek(&arp_q))
arp_queue_kick();
}
/* Create and send our response to an ARP request. */ /* Create and send our response to an ARP request. */
static int static int
arp_response(struct arphdr *arp1, struct device *dev, int addrtype) arp_response(struct arphdr *arp1, struct device *dev, int addrtype)
...@@ -753,6 +777,8 @@ arp_queue(struct sk_buff *skb) ...@@ -753,6 +777,8 @@ arp_queue(struct sk_buff *skb)
printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic); printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
return; return;
} }
if(arp_q==NULL)
arp_queue_kick();
skb_queue_tail(&arp_q,skb); skb_queue_tail(&arp_q,skb);
skb->magic = ARP_QUEUE_MAGIC; skb->magic = ARP_QUEUE_MAGIC;
sti(); sti();
......
...@@ -186,7 +186,7 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait) ...@@ -186,7 +186,7 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait)
return(0); return(0);
case SEL_OUT: case SEL_OUT:
if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) if (sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
{ {
return(1); return(1);
} }
......
...@@ -253,17 +253,33 @@ static inline int bad_mask(unsigned long mask, unsigned long addr) ...@@ -253,17 +253,33 @@ static inline int bad_mask(unsigned long mask, unsigned long addr)
static int rt_new(struct rtentry *r) static int rt_new(struct rtentry *r)
{ {
struct device *dev; int err;
char * devname;
struct device * dev = NULL;
unsigned long flags, daddr, mask, gw; unsigned long flags, daddr, mask, gw;
if ((devname = r->rt_dev) != NULL) {
err = getname(devname, &devname);
if (err)
return err;
dev = dev_get(devname);
putname(devname);
if (!dev)
return -EINVAL;
}
if (r->rt_dst.sa_family != AF_INET) if (r->rt_dst.sa_family != AF_INET)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
flags = r->rt_flags; flags = r->rt_flags;
daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr; daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
mask = r->rt_genmask; mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr; gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
dev = (struct device *) r->rt_dev;
if (flags & RTF_HOST)
mask = 0xffffffff;
else if (r->rt_genmask.sa_family != AF_INET)
return -EAFNOSUPPORT;
if (flags & RTF_GATEWAY) { if (flags & RTF_GATEWAY) {
if (r->rt_gateway.sa_family != AF_INET) if (r->rt_gateway.sa_family != AF_INET)
...@@ -343,19 +359,41 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt) ...@@ -343,19 +359,41 @@ struct rtable * rt_route(unsigned long daddr, struct options *opt)
return NULL; return NULL;
} }
static int get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
{
int err;
struct old_rtentry tmp;
err=verify_area(VERIFY_READ, src, sizeof(*src));
if (err)
return err;
memcpy_fromfs(&tmp, src, sizeof(*src));
memset(rt, 0, sizeof(*rt));
rt->rt_dst = tmp.rt_dst;
rt->rt_gateway = tmp.rt_gateway;
rt->rt_genmask.sa_family = AF_INET;
((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
rt->rt_flags = tmp.rt_flags;
rt->rt_dev = tmp.rt_dev;
return 0;
}
int rt_ioctl(unsigned int cmd, void *arg) int rt_ioctl(unsigned int cmd, void *arg)
{ {
struct device *dev;
struct rtentry rt;
char *devname;
int ret;
int err; int err;
struct rtentry rt;
switch(cmd) { switch(cmd) {
case DDIOCSDBG: case DDIOCSDBG:
ret = dbg_ioctl(arg, DBG_RT); return dbg_ioctl(arg, DBG_RT);
break; case SIOCADDRTOLD:
case SIOCDELRTOLD:
if (!suser())
return -EPERM;
err = get_old_rtent((struct old_rtentry *) arg, &rt);
if (err)
return err;
return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
case SIOCADDRT: case SIOCADDRT:
case SIOCDELRT: case SIOCDELRT:
if (!suser()) if (!suser())
...@@ -364,21 +402,8 @@ int rt_ioctl(unsigned int cmd, void *arg) ...@@ -364,21 +402,8 @@ int rt_ioctl(unsigned int cmd, void *arg)
if (err) if (err)
return err; return err;
memcpy_fromfs(&rt, arg, sizeof(struct rtentry)); memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
if ((devname = (char *) rt.rt_dev) != NULL) { return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
err = getname(devname, &devname);
if (err)
return err;
dev = dev_get(devname);
putname(devname);
if (!dev)
return -EINVAL;
rt.rt_dev = dev;
}
ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
break;
default:
ret = -EINVAL;
} }
return ret; return -EINVAL;
} }
...@@ -1531,8 +1531,8 @@ inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1531,8 +1531,8 @@ inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case DDIOCSDBG: case DDIOCSDBG:
return(dbg_ioctl((void *) arg, DBG_INET)); return(dbg_ioctl((void *) arg, DBG_INET));
case SIOCADDRT: case SIOCADDRT: case SIOCADDRTOLD:
case SIOCDELRT: case SIOCDELRT: case SIOCDELRTOLD:
return(rt_ioctl(cmd,(void *) arg)); return(rt_ioctl(cmd,(void *) arg));
case SIOCDARP: case SIOCDARP:
...@@ -1595,7 +1595,7 @@ sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority) ...@@ -1595,7 +1595,7 @@ sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
{ {
if (sk) { if (sk) {
if (sk->rmem_alloc + size < sk->rcvbuf || force) { if (sk->rmem_alloc + size < sk->rcvbuf || force) {
void *c = alloc_skb(size, priority); struct sk_buff *c = alloc_skb(size, priority);
cli(); cli();
if (c) sk->rmem_alloc += size; if (c) sk->rmem_alloc += size;
sti(); sti();
......
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