Commit 9300725c authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.15i

parent 0acb47cd
VERSION = 0.99 VERSION = 0.99
PATCHLEVEL = 15 PATCHLEVEL = 15
ALPHA = h ALPHA = i
all: Version zImage all: Version zImage
......
Linux kernel release 0.99 patchlevel 14 Linux kernel release 0.99 patchlevel 15
These are the release notes for linux version 0.99.14. Read them These are the release notes for linux version 0.99.15. Read them
carefully, as they tell you what's new, explain how to install the carefully, as they tell you what's new, explain how to install the
kernel, and what to do if something goes wrong. kernel, and what to do if something goes wrong.
INSTALLING the kernel: INSTALLING the kernel:
- if you install by patching, you need a *clean* 0.99.13 source tree, - if you install by patching, you need a *clean* 0.99.14 source tree,
which presumably exists in /usr/src/linux. If so, to get the kernel which presumably exists in /usr/src/linux. If so, to get the kernel
patched, just do a patched, just do a
cd /usr/src cd /usr/src
patch -p0 < linux-0.99.patch14 patch -p0 < linux-0.99.patch15
and you should be ok. You may want to remove the backup files (xxx~ and you should be ok. You may want to remove the backup files (xxx~
or xxx.orig), and make sure that there are no failed patches (xxx# or or xxx.orig), and make sure that there are no failed patches (xxx# or
...@@ -21,7 +21,7 @@ INSTALLING the kernel: ...@@ -21,7 +21,7 @@ INSTALLING the kernel:
- If you install the full sources, do a - If you install the full sources, do a
cd /usr/src cd /usr/src
tar xvf linux-0.99.14.tar tar xvf linux-0.99.15.tar
to get it all put in place. to get it all put in place.
......
...@@ -97,9 +97,19 @@ void emu_printall() ...@@ -97,9 +97,19 @@ void emu_printall()
printk(" [%02x]", byte1); printk(" [%02x]", byte1);
address++; address++;
} }
if ( i == MAX_PRINTED_BYTES ) printk(" [more..]"); if ( i == MAX_PRINTED_BYTES )
printk("\n"); printk(" [more..]\n");
FPU_modrm = get_fs_byte(1 + (unsigned char *) address); else
{
FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
if (FPU_modrm >= 0300)
printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
else
printk(" /%d, mod=%d rm=%d\n",
(FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
}
partial_status = status_word(); partial_status = status_word();
#ifdef DEBUGGING #ifdef DEBUGGING
...@@ -118,12 +128,6 @@ if ( partial_status & SW_Denorm_Op ) printk("SW: denormalized operand\n"); ...@@ -118,12 +128,6 @@ if ( partial_status & SW_Denorm_Op ) printk("SW: denormalized operand\n");
if ( partial_status & SW_Invalid ) printk("SW: invalid operation\n"); if ( partial_status & SW_Invalid ) printk("SW: invalid operation\n");
#endif DEBUGGING #endif DEBUGGING
if (FPU_modrm >= 0300)
printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
else
printk("/%d, mod=%d rm=%d\n",
(FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
partial_status & 0x8000 ? 1 : 0, /* busy */ partial_status & 0x8000 ? 1 : 0, /* busy */
(partial_status & 0x3800) >> 11, /* stack top pointer */ (partial_status & 0x3800) >> 11, /* stack top pointer */
......
...@@ -51,11 +51,10 @@ int reg_mul(FPU_REG const *a, FPU_REG const *b, ...@@ -51,11 +51,10 @@ int reg_mul(FPU_REG const *a, FPU_REG const *b,
one valid and the other zero. one valid and the other zero.
The result is therefore zero. */ The result is therefore zero. */
reg_move(&CONST_Z, dest); reg_move(&CONST_Z, dest);
#ifdef PECULIAR_486
/* The 80486 book says that the answer is +0, but a real /* The 80486 book says that the answer is +0, but a real
80486 appears to behave this way... */ 80486 behaves this way.
IEEE-754 apparently says it should be this way. */
dest->sign = sign; dest->sign = sign;
#endif PECULIAR_486
return 0; return 0;
} }
else else
......
...@@ -1828,6 +1828,14 @@ static void clear_selection() ...@@ -1828,6 +1828,14 @@ static void clear_selection()
/* /*
* PIO_FONT support. * PIO_FONT support.
*
* The font loading code goes back to the codepage package by
* Joel Hoffman (joel@wam.umd.edu). (He reports that the original
* reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
* Video Systems_ by Richard Wilton. 1987. Microsoft Press".)
*
* Change for certain monochrome monitors by Yury Shevchuck
* (sizif@botik.yaroslavl.su).
*/ */
#define colourmap ((char *)0xa0000) #define colourmap ((char *)0xa0000)
...@@ -1843,14 +1851,17 @@ static int set_get_font(char * arg, int set) ...@@ -1843,14 +1851,17 @@ static int set_get_font(char * arg, int set)
#ifdef CAN_LOAD_EGA_FONTS #ifdef CAN_LOAD_EGA_FONTS
int i; int i;
char *charmap; char *charmap;
int beg;
/* no use to "load" CGA... */ /* no use to "load" CGA... */
if (video_type == VIDEO_TYPE_EGAC) if (video_type == VIDEO_TYPE_EGAC) {
charmap = colourmap; charmap = colourmap;
else if (video_type == VIDEO_TYPE_EGAM) beg = 0x0e;
} else if (video_type == VIDEO_TYPE_EGAM) {
charmap = blackwmap; charmap = blackwmap;
else beg = 0x0a;
} else
return -EINVAL; return -EINVAL;
i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz); i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
...@@ -1897,7 +1908,7 @@ static int set_get_font(char * arg, int set) ...@@ -1897,7 +1908,7 @@ static int set_get_font(char * arg, int set)
outb_p( 0x05, gr_port_reg ); outb_p( 0x05, gr_port_reg );
outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */ outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */
outb_p( 0x06, gr_port_reg ); outb_p( 0x06, gr_port_reg );
outb_p( 0x0e, gr_port_val ); /* map starts at b800:0000 */ outb_p( beg, gr_port_val ); /* map starts at b800:0 or b000:0 */
sti(); sti();
return 0; return 0;
......
...@@ -930,10 +930,7 @@ int is_ignored(int sig) ...@@ -930,10 +930,7 @@ int is_ignored(int sig)
static inline int input_available_p(struct tty_struct *tty) static inline int input_available_p(struct tty_struct *tty)
{ {
/* Avoid calling TTY_READ_FLUSH unnecessarily. */ /* Avoid calling TTY_READ_FLUSH unnecessarily. */
if (L_ICANON(tty)) { if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
if (tty->canon_data || FULL(&tty->read_q))
return 1;
} else if (!EMPTY(&tty->secondary))
return 1; return 1;
/* Shuffle any pending data down the queues. */ /* Shuffle any pending data down the queues. */
...@@ -941,10 +938,7 @@ static inline int input_available_p(struct tty_struct *tty) ...@@ -941,10 +938,7 @@ static inline int input_available_p(struct tty_struct *tty)
if (tty->link) if (tty->link)
TTY_WRITE_FLUSH(tty->link); TTY_WRITE_FLUSH(tty->link);
if (L_ICANON(tty)) { if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
if (tty->canon_data || FULL(&tty->read_q))
return 1;
} else if (!EMPTY(&tty->secondary))
return 1; return 1;
return 0; return 0;
} }
...@@ -1036,7 +1030,7 @@ static int read_chan(struct tty_struct *tty, struct file *file, ...@@ -1036,7 +1030,7 @@ static int read_chan(struct tty_struct *tty, struct file *file,
nr--; nr--;
} }
while (nr > 0) { while (1) {
int eol; int eol;
cli(); cli();
...@@ -1047,6 +1041,24 @@ static int read_chan(struct tty_struct *tty, struct file *file, ...@@ -1047,6 +1041,24 @@ static int read_chan(struct tty_struct *tty, struct file *file,
eol = clear_bit(tty->secondary.tail, eol = clear_bit(tty->secondary.tail,
&tty->secondary_flags); &tty->secondary_flags);
c = tty->secondary.buf[tty->secondary.tail]; c = tty->secondary.buf[tty->secondary.tail];
if (!nr) {
/* Gobble up an immediately following EOF if
there is no more room in buf (this can
happen if the user "pushes" some characters
using ^D). This prevents the next read()
from falsely returning EOF. */
if (eol) {
if (c == __DISABLED_CHAR) {
tty->canon_data--;
INC(tty->secondary.tail);
} else {
set_bit(tty->secondary.tail,
&tty->secondary_flags);
}
}
sti();
break;
}
INC(tty->secondary.tail); INC(tty->secondary.tail);
sti(); sti();
if (eol) { if (eol) {
...@@ -1067,10 +1079,9 @@ static int read_chan(struct tty_struct *tty, struct file *file, ...@@ -1067,10 +1079,9 @@ static int read_chan(struct tty_struct *tty, struct file *file,
/* If there is enough space in the secondary queue now, let the /* If there is enough space in the secondary queue now, let the
low-level driver know. */ low-level driver know. */
if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW) if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
&& !clear_bit(TTY_SQ_THROTTLED, &tty->flags)) && clear_bit(TTY_SQ_THROTTLED, &tty->flags))
tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL); tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
/* XXX packet mode's status byte is mistakenly counted */
if (b - buf >= minimum || !nr) if (b - buf >= minimum || !nr)
break; break;
if (time) if (time)
...@@ -1121,6 +1132,10 @@ static int write_chan(struct tty_struct * tty, struct file * file, ...@@ -1121,6 +1132,10 @@ static int write_chan(struct tty_struct * tty, struct file * file,
break; break;
if (EMPTY(&tty->write_q) && !need_resched) if (EMPTY(&tty->write_q) && !need_resched)
continue; continue;
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
schedule(); schedule();
} }
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
...@@ -1594,7 +1609,7 @@ static int normal_select(struct tty_struct * tty, struct inode * inode, ...@@ -1594,7 +1609,7 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
select_wait(&tty->secondary.proc_list, wait); select_wait(&tty->secondary.proc_list, wait);
return 0; return 0;
case SEL_OUT: case SEL_OUT:
if (!FULL(&tty->write_q)) if (LEFT(&tty->write_q) > WAKEUP_CHARS)
return 1; return 1;
select_wait(&tty->write_q.proc_list, wait); select_wait(&tty->write_q.proc_list, wait);
return 0; return 0;
......
...@@ -487,6 +487,8 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -487,6 +487,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
sizeof (pid_t)); sizeof (pid_t));
if (retval) if (retval)
return retval; return retval;
if (current->tty != termios_dev)
return -ENOTTY;
put_fs_long(termios_tty->pgrp, (pid_t *) arg); put_fs_long(termios_tty->pgrp, (pid_t *) arg);
return 0; return 0;
case TIOCSPGRP: case TIOCSPGRP:
...@@ -526,7 +528,7 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -526,7 +528,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
return 0; return 0;
case TIOCSTI: case TIOCSTI:
if ((current->tty != dev) && !suser()) if ((current->tty != dev) && !suser())
return -EACCES; return -EPERM;
retval = verify_area(VERIFY_READ, (void *) arg, 1); retval = verify_area(VERIFY_READ, (void *) arg, 1);
if (retval) if (retval)
return retval; return retval;
...@@ -580,7 +582,7 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -580,7 +582,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
else if (IS_A_PTY_SLAVE(dev)) else if (IS_A_PTY_SLAVE(dev))
redirect = tty; redirect = tty;
else else
return -EINVAL; return -ENOTTY;
return 0; return 0;
case FIONBIO: case FIONBIO:
arg = get_fs_long((unsigned long *) arg); arg = get_fs_long((unsigned long *) arg);
...@@ -590,8 +592,8 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -590,8 +592,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
file->f_flags &= ~O_NONBLOCK; file->f_flags &= ~O_NONBLOCK;
return 0; return 0;
case TIOCNOTTY: case TIOCNOTTY:
if (MINOR(file->f_rdev) != current->tty) if (current->tty != dev)
return -EINVAL; return -ENOTTY;
if (current->leader) if (current->leader)
disassociate_ctty(0); disassociate_ctty(0);
current->tty = -1; current->tty = -1;
...@@ -629,7 +631,7 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -629,7 +631,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
return 0; return 0;
case TIOCPKT: case TIOCPKT:
if (!IS_A_PTY_MASTER(dev)) if (!IS_A_PTY_MASTER(dev))
return -EINVAL; return -ENOTTY;
retval = verify_area(VERIFY_READ, (void *) arg, retval = verify_area(VERIFY_READ, (void *) arg,
sizeof (unsigned long)); sizeof (unsigned long));
if (retval) if (retval)
...@@ -637,7 +639,7 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -637,7 +639,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
if (get_fs_long(arg)) { if (get_fs_long(arg)) {
if (!tty->packet) { if (!tty->packet) {
tty->packet = 1; tty->packet = 1;
tty->ctrl_status = 0; tty->link->ctrl_status = 0;
} }
} else } else
tty->packet = 0; tty->packet = 0;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/ */
static char *version = "3c509.c:pl13t 11/24/93 becker@super.org\n"; static char *version = "3c509.c:pl15i 2/23/94 becker@super.org\n";
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -549,19 +549,19 @@ el3_rx(struct device *dev) ...@@ -549,19 +549,19 @@ el3_rx(struct device *dev)
inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) { while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
if (rx_status & 0x4000) { /* Error, update stats. */ if (rx_status & 0x4000) { /* Error, update stats. */
short error = rx_status & 0x3C00; short error = rx_status & 0x3800;
lp->stats.rx_errors++; lp->stats.rx_errors++;
switch (error) { switch (error) {
case 0x2000: lp->stats.rx_over_errors++; break; case 0x0000: lp->stats.rx_over_errors++; break;
case 0x2C00: lp->stats.rx_length_errors++; break; case 0x0800: lp->stats.rx_length_errors++; break;
case 0x3400: lp->stats.rx_crc_errors++; break; case 0x1000: lp->stats.rx_frame_errors++; break;
case 0x2400: lp->stats.rx_length_errors++; break; case 0x1800: lp->stats.rx_length_errors++; break;
case 0x3000: lp->stats.rx_frame_errors++; break; case 0x2000: lp->stats.rx_frame_errors++; break;
case 0x0800: lp->stats.rx_frame_errors++; break; case 0x2800: lp->stats.rx_crc_errors++; break;
} }
} }
if ( (! (rx_status & 0x4000)) if ( (! (rx_status & 0x4000))
|| ! (rx_status & 0x2000)) { /* Dribble bits are OK. */ || ! (rx_status & 0x1000)) { /* Dribble bits are OK. */
short pkt_len = rx_status & 0x7ff; short pkt_len = rx_status & 0x7ff;
int sksize = sizeof(struct sk_buff) + pkt_len + 3; int sksize = sizeof(struct sk_buff) + pkt_len + 3;
struct sk_buff *skb; struct sk_buff *skb;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
*/ */
static char *version = static char *version =
"atp.c:v0.03 1/19/94 Donald Becker (becker@super.org)\n"; "atp.c:v0.04 2/25/94 Donald Becker (becker@super.org)\n";
/* /*
This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket
...@@ -477,7 +477,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -477,7 +477,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
/* For ethernet, fill in the header. This should really be done by a /* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */ higher level, rather than duplicated for each ethernet adaptor. */
if (!skb->arp && dev->rebuild_header(skb+1, dev)) { if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
skb->dev = dev; skb->dev = dev;
arp_queue (skb); arp_queue (skb);
return 0; return 0;
...@@ -490,7 +490,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) ...@@ -490,7 +490,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
printk("%s: Transmitter access conflict.\n", dev->name); printk("%s: Transmitter access conflict.\n", dev->name);
else { else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = (void *)(skb+1); unsigned char *buf = skb->data;
int flags; int flags;
/* Disable interrupts by writing 0x00 to the Interrupt Mask Register. /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
...@@ -611,7 +611,7 @@ net_interrupt(int reg_ptr) ...@@ -611,7 +611,7 @@ net_interrupt(int reg_ptr)
} else if (num_tx_since_rx > 8 } else if (num_tx_since_rx > 8
&& jiffies > dev->last_rx + 100) { && jiffies > dev->last_rx + 100) {
if (net_debug > 2) if (net_debug > 2)
printk("%s: Missed packet? No Rx after %d Tx and %d jiffies" printk("%s: Missed packet? No Rx after %d Tx and %ld jiffies"
" status %02x CMR1 %02x.\n", dev->name, " status %02x CMR1 %02x.\n", dev->name,
num_tx_since_rx, jiffies - dev->last_rx, status, num_tx_since_rx, jiffies - dev->last_rx, status,
(read_nibble(ioaddr, CMR1) >> 3) & 15); (read_nibble(ioaddr, CMR1) >> 3) & 15);
...@@ -623,6 +623,8 @@ net_interrupt(int reg_ptr) ...@@ -623,6 +623,8 @@ net_interrupt(int reg_ptr)
break; break;
} }
/* This following code fixes a rare (and very difficult to track down)
problem where the adaptor forgets its ethernet address. */
{ {
int i; int i;
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
...@@ -686,12 +688,12 @@ static void net_rx(struct device *dev) ...@@ -686,12 +688,12 @@ static void net_rx(struct device *dev)
skb->len = pkt_len; skb->len = pkt_len;
skb->dev = dev; skb->dev = dev;
/* 'skb+1' points to the start of sk_buff data area. */ read_block(ioaddr, pkt_len, skb->data, dev->if_port);
read_block(ioaddr, pkt_len, (unsigned char *)(skb + 1), dev->if_port);
if (net_debug > 6) { if (net_debug > 6) {
unsigned char *data = (unsigned char *)(skb + 1); unsigned char *data = skb->data;
printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x..", printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x"
"%02x%02x%02x %02x%02x..",
data[0], data[1], data[2], data[3], data[4], data[5], data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10], data[11], data[6], data[7], data[8], data[9], data[10], data[11],
data[12], data[13]); data[12], data[13]);
......
...@@ -135,8 +135,6 @@ static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n"; ...@@ -135,8 +135,6 @@ static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n";
#include "arp.h" #include "arp.h"
#include "depca.h" #include "depca.h"
extern int vsprintf(char *buf, const char *fmt, ...);
#ifdef DEPCA_DEBUG #ifdef DEPCA_DEBUG
int depca_debug = DEPCA_DEBUG; int depca_debug = DEPCA_DEBUG;
#else #else
...@@ -344,7 +342,7 @@ int depca_probe(struct device *dev) ...@@ -344,7 +342,7 @@ int depca_probe(struct device *dev)
(num_eth > 0) && (num_eth < 9999)) { (num_eth > 0) && (num_eth < 9999)) {
dev = dev->next; /* point to the new device */ dev = dev->next; /* point to the new device */
dev->name = (char *)(dev + sizeof(struct device)); dev->name = (char *)(dev + sizeof(struct device));
vsprintf(dev->name,"eth%d", num_eth); /* New device name */ sprintf(dev->name,"eth%d", num_eth); /* New device name */
dev->base_addr = ioaddr; /* assign the io address */ dev->base_addr = ioaddr; /* assign the io address */
dev->next = (struct device *)NULL; /* mark the end of list */ dev->next = (struct device *)NULL; /* mark the end of list */
dev->init = &depca_probe;/* initialisation routine */ dev->init = &depca_probe;/* initialisation routine */
......
...@@ -562,9 +562,9 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -562,9 +562,9 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
(int)(lp->tx_bounce_buffs + entry) | 0x83000000; (int)(lp->tx_bounce_buffs + entry) | 0x83000000;
if (skb->free) if (skb->free)
kfree_skb (skb, FREE_WRITE); kfree_skb (skb, FREE_WRITE);
} else } else {
{ /* We can't free the packet yet, so we inform the memory management
/* Gimme!!! */ code that we are still using it. */
if(skb->free==0) if(skb->free==0)
skb_kept_by_device(skb); skb_kept_by_device(skb);
lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000; lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000;
...@@ -655,7 +655,8 @@ lance_interrupt(int reg_ptr) ...@@ -655,7 +655,8 @@ lance_interrupt(int reg_ptr)
kfree_skb(skb, FREE_WRITE); kfree_skb(skb, FREE_WRITE);
else else
skb_device_release(skb,FREE_WRITE); skb_device_release(skb,FREE_WRITE);
/* Warning: skb may well vanish at the point you call device_release! */ /* Warning: skb may well vanish at the point you call
device_release! */
} }
dirty_tx++; dirty_tx++;
} }
...@@ -705,8 +706,13 @@ lance_rx(struct device *dev) ...@@ -705,8 +706,13 @@ lance_rx(struct device *dev)
while (lp->rx_ring[entry].base >= 0) { while (lp->rx_ring[entry].base >= 0) {
int status = lp->rx_ring[entry].base >> 24; int status = lp->rx_ring[entry].base >> 24;
if (status & 0x40) { /* There was an error. */ if (status != 0x03) { /* There was an error. */
lp->stats.rx_errors++; /* There is an tricky error noted by John Murphy,
<murf@perftech.com> to Russ Nelson: Even with full-sized
buffers it's possible for a jabber packet to use two
buffers, with only the last correctly noting the error. */
if (status & 0x01) /* Only count a general error at the */
lp->stats.rx_errors++; /* end of a packet.*/
if (status & 0x20) lp->stats.rx_frame_errors++; if (status & 0x20) lp->stats.rx_frame_errors++;
if (status & 0x10) lp->stats.rx_over_errors++; if (status & 0x10) lp->stats.rx_over_errors++;
if (status & 0x08) lp->stats.rx_crc_errors++; if (status & 0x08) lp->stats.rx_crc_errors++;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
*/ */
static char *version = static char *version =
"smc-ultra.c:v0.06 2/9/94 Donald Becker (becker@super.org)\n"; "smc-ultra.c:v0.07 3/1/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -63,7 +63,7 @@ int ultra_probe(struct device *dev) ...@@ -63,7 +63,7 @@ int ultra_probe(struct device *dev)
unsigned short ioaddr = dev->base_addr; unsigned short ioaddr = dev->base_addr;
if (ioaddr > 0x1ff) if (ioaddr > 0x1ff)
return ! ultraprobe1(ioaddr, dev); return ultraprobe1(ioaddr, dev);
else if (ioaddr > 0) else if (ioaddr > 0)
return ENXIO; /* Don't probe at all. */ return ENXIO; /* Don't probe at all. */
...@@ -158,7 +158,7 @@ int ultraprobe1(int ioaddr, struct device *dev) ...@@ -158,7 +158,7 @@ int ultraprobe1(int ioaddr, struct device *dev)
dev->mem_end = dev->rmem_end dev->mem_end = dev->rmem_end
= dev->mem_start + (ei_status.stop_page - START_PG)*256; = dev->mem_start + (ei_status.stop_page - START_PG)*256;
printk(",%s IRQ %d memory %#x-%#x.\n", eeprom_irq ? "" : "assigned ", printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
dev->irq, dev->mem_start, dev->mem_end-1); dev->irq, dev->mem_start, dev->mem_end-1);
if (ei_debug > 0) if (ei_debug > 0)
printk(version); printk(version);
...@@ -193,7 +193,7 @@ ultra_reset_8390(struct device *dev) ...@@ -193,7 +193,7 @@ ultra_reset_8390(struct device *dev)
int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */ int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
outb(ULTRA_RESET, cmd_port); outb(ULTRA_RESET, cmd_port);
if (ei_debug > 1) printk("resetting Ultra, t=%d...", jiffies); if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
ei_status.txing = 0; ei_status.txing = 0;
outb(ULTRA_MEMENB, cmd_port); outb(ULTRA_MEMENB, cmd_port);
......
Linux can read, but not write, OS/2 HPFS partitions.
Mount options are the same as for msdos partitions.
uid=nnn All files in the partition will be owned by user id nnn.
gid=nnn All files in the partition will be in group nnn.
umask=nnn The permission mask (see umask(1)) for the partition.
conv=binary Data is returned exactly as is, with CRLF's. [default]
conv=text (Carriage return, line feed) is replaced with newline.
conv=auto Chooses, file by file, conv=binary or conv=text (by guessing)
There is one mount option unique to HPFS.
case=lower Convert file names to lower case. [default]
case=asis Return file names as is, in mixed case.
Case is not significant in filename matching, like real HPFS.
Command line example
mkdir -p /os2/c
mount -t hpfs -o uid=100,gid=100 /dev/sda6 /os2/c
/etc/fstab example
/dev/sdb5 /d/f hpfs ro,uid=402,gid=402,umask=002
...@@ -131,7 +131,7 @@ struct hpfs_spare_block ...@@ -131,7 +131,7 @@ struct hpfs_spare_block
/* The code page info pointed to by the spare block consists of an index /* The code page info pointed to by the spare block consists of an index
block and blocks containing character maps. The following is pretty block and blocks containing character maps. The following is pretty
sketchy, but Linux is Latin-1 so it doesn't matter. */ sketchy, but Linux doesn't use code pages so it doesn't matter. */
/* block pointed to by spareblock->code_page_dir */ /* block pointed to by spareblock->code_page_dir */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Chris Smith 1993 * Chris Smith 1993
* *
* Sources & references: * Sources & references:
* Duncan, _Design ... of HPFS_, MSSJ 4(5) (C) 1989 Microsoft Corp * Duncan, _Design ... of HPFS_, MSJ 4(5) (C) 1989 Microsoft Corp
* linux/fs/minix Copyright (C) 1991, 1992, 1993 Linus Torvalds * linux/fs/minix Copyright (C) 1991, 1992, 1993 Linus Torvalds
* linux/fs/msdos Written 1992, 1993 by Werner Almesberger * linux/fs/msdos Written 1992, 1993 by Werner Almesberger
* linux/fs/isofs Copyright (C) 1991 Eric Youngdale * linux/fs/isofs Copyright (C) 1991 Eric Youngdale
......
...@@ -191,6 +191,8 @@ static int isofs_readdir(struct inode * inode, struct file * filp, ...@@ -191,6 +191,8 @@ static int isofs_readdir(struct inode * inode, struct file * filp,
for (i = 0; i < dlen && i < NAME_MAX; i++) { for (i = 0; i < dlen && i < NAME_MAX; i++) {
if (!(c = dpnt[i])) break; if (!(c = dpnt[i])) break;
if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */ if (c >= 'A' && c <= 'Z') c |= 0x20; /* lower case */
if (c == '.' && i == dlen-3 && de->name[i+1] == ';' && de->name[i+2] == '1')
break; /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
if (c == ';' && i == dlen-2 && de->name[i+1] == '1') if (c == ';' && i == dlen-2 && de->name[i+1] == '1')
break; /* Drop trailing ';1' */ break; /* Drop trailing ';1' */
if (c == ';') c = '.'; /* Convert remaining ';' to '.' */ if (c == ';') c = '.'; /* Convert remaining ';' to '.' */
......
...@@ -316,6 +316,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de, ...@@ -316,6 +316,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
struct SL_component * slp; struct SL_component * slp;
slen = rr->len - 5; slen = rr->len - 5;
slp = &rr->u.SL.link; slp = &rr->u.SL.link;
inode->i_size = 0;
while (slen > 1){ while (slen > 1){
rootflag = 0; rootflag = 0;
switch(slp->flags &~1){ switch(slp->flags &~1){
......
...@@ -108,7 +108,7 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end) ...@@ -108,7 +108,7 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
continue; continue;
if (server->flags & NFS_MOUNT_SOFT) { if (server->flags & NFS_MOUNT_SOFT) {
printk("NFS server %s not responding, " printk("NFS server %s not responding, "
"timed out", server_name); "timed out\n", server_name);
result = -EIO; result = -EIO;
break; break;
} }
......
...@@ -84,7 +84,8 @@ void proc_read_inode(struct inode * inode) ...@@ -84,7 +84,8 @@ void proc_read_inode(struct inode * inode)
inode->i_nlink = 1; inode->i_nlink = 1;
inode->i_size = 0; inode->i_size = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = inode->i_blksize = 0; inode->i_blocks = 0;
inode->i_blksize = 1024;
ino = inode->i_ino; ino = inode->i_ino;
pid = ino >> 16; pid = ino >> 16;
p = task[0]; p = task[0];
......
...@@ -223,11 +223,10 @@ asmlinkage int sys_select( unsigned long *buffer ) ...@@ -223,11 +223,10 @@ asmlinkage int sys_select( unsigned long *buffer )
i = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp)); i = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
if (i) if (i)
return i; return i;
timeout = jiffies; timeout = ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
timeout += ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ; timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
if (timeout <= jiffies) if (timeout)
timeout = 0; timeout += jiffies + 1;
} }
current->timeout = timeout; current->timeout = timeout;
i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex); i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex);
......
...@@ -166,7 +166,7 @@ struct tss_struct { ...@@ -166,7 +166,7 @@ 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 */ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter; long counter;
long priority; long priority;
unsigned long signal; unsigned long signal;
......
...@@ -150,9 +150,9 @@ struct termios { ...@@ -150,9 +150,9 @@ struct termios {
#define VTDLY 0040000 #define VTDLY 0040000
#define VT0 0000000 #define VT0 0000000
#define VT1 0040000 #define VT1 0040000
#define FFDLY 0040000 #define FFDLY 0100000
#define FF0 0000000 #define FF0 0000000
#define FF1 0040000 #define FF1 0100000
/* c_cflag bit meaning */ /* c_cflag bit meaning */
#define CBAUD 0000017 #define CBAUD 0000017
......
...@@ -462,6 +462,8 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) ...@@ -462,6 +462,8 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
shp->attaches = shmd; shp->attaches = shmd;
shp->shm_lpid = current->pid; shp->shm_lpid = current->pid;
shp->shm_atime = CURRENT_TIME; shp->shm_atime = CURRENT_TIME;
if (!raddr)
return addr;
put_fs_long (addr, raddr); put_fs_long (addr, raddr);
return 0; return 0;
} }
......
...@@ -80,23 +80,33 @@ asmlinkage void alignment_check(void); ...@@ -80,23 +80,33 @@ asmlinkage void alignment_check(void);
/*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err) /*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
{ {
int i; int i;
unsigned long esp;
unsigned short ss;
esp = (unsigned long) &regs->esp;
ss = KERNEL_DS;
if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3) if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
return; return;
if (regs->cs & 3) {
esp = regs->esp;
ss = regs->ss;
}
console_verbose(); console_verbose();
printk("%s: %04lx\n", str, err & 0xffff); printk("%s: %04lx\n", str, err & 0xffff);
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\n", printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp); regs->esi, regs->edi, regs->ebp, esp);
printk("ds: %04x es: %04x fs: %04x gs: %04x\n", printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
regs->ds, regs->es, regs->fs, regs->gs); regs->ds, regs->es, regs->fs, regs->gs, ss);
store_TR(i); store_TR(i);
printk("Pid: %d, process nr: %d (%s)\n", current->pid, 0xffff & i, current->comm); printk("Pid: %d, process nr: %d (%s)\nCode: ", current->pid, 0xffff & i, current->comm);
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("\nStack: ");
for(i=0;i<5;i++)
printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp)));
printk("\n"); printk("\n");
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
......
...@@ -304,9 +304,9 @@ int unmap_page_range(unsigned long from, unsigned long size) ...@@ -304,9 +304,9 @@ int unmap_page_range(unsigned long from, unsigned long size)
if ((page = *page_table) != 0) { if ((page = *page_table) != 0) {
*page_table = 0; *page_table = 0;
if (1 & page) { if (1 & page) {
if (!(mem_map[MAP_NR(page)] if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
& MAP_PAGE_RESERVED)) if (current->rss > 0)
--current->rss; --current->rss;
free_page(PAGE_MASK & page); free_page(PAGE_MASK & page);
} else } else
swap_free(page); swap_free(page);
...@@ -364,9 +364,9 @@ int zeromap_page_range(unsigned long from, unsigned long size, int mask) ...@@ -364,9 +364,9 @@ int zeromap_page_range(unsigned long from, unsigned long size, int mask)
if ((page = *page_table) != 0) { if ((page = *page_table) != 0) {
*page_table = 0; *page_table = 0;
if (page & PAGE_PRESENT) { if (page & PAGE_PRESENT) {
if (!(mem_map[MAP_NR(page)] if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
& MAP_PAGE_RESERVED)) if (current->rss > 0)
--current->rss; --current->rss;
free_page(PAGE_MASK & page); free_page(PAGE_MASK & page);
} else } else
swap_free(page); swap_free(page);
...@@ -426,9 +426,9 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size, i ...@@ -426,9 +426,9 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size, i
if ((page = *page_table) != 0) { if ((page = *page_table) != 0) {
*page_table = 0; *page_table = 0;
if (PAGE_PRESENT & page) { if (PAGE_PRESENT & page) {
if (!(mem_map[MAP_NR(page)] if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
& MAP_PAGE_RESERVED)) if (current->rss > 0)
--current->rss; --current->rss;
free_page(PAGE_MASK & page); free_page(PAGE_MASK & page);
} else } else
swap_free(page); swap_free(page);
......
...@@ -210,9 +210,11 @@ icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev) ...@@ -210,9 +210,11 @@ icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev)
ip = iph->daddr; ip = iph->daddr;
switch(icmph->code & 7) { switch(icmph->code & 7) {
case ICMP_REDIR_NET: case ICMP_REDIR_NET:
#ifdef not_a_good_idea
rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
ip, 0, icmph->un.gateway, dev); ip, 0, icmph->un.gateway, dev);
break; break;
#endif
case ICMP_REDIR_HOST: case ICMP_REDIR_HOST:
rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY), rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
ip, 0, icmph->un.gateway, dev); ip, 0, icmph->un.gateway, dev);
......
...@@ -394,8 +394,8 @@ void kfree_skb(struct sk_buff *skb, int rw) ...@@ -394,8 +394,8 @@ void kfree_skb(struct sk_buff *skb, int rw)
skb->magic = 0; skb->magic = 0;
if (skb->sk) if (skb->sk)
{ {
if(skb->sk->prot!=NULL) if(skb->sk->prot!=NULL)
{ {
if (rw) if (rw)
skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len); skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
else else
......
...@@ -1578,10 +1578,13 @@ sock_wmalloc(struct sock *sk, unsigned long size, int force, ...@@ -1578,10 +1578,13 @@ sock_wmalloc(struct sock *sk, unsigned long size, int force,
{ {
if (sk) { if (sk) {
if (sk->wmem_alloc + size < sk->sndbuf || force) { if (sk->wmem_alloc + size < sk->sndbuf || force) {
cli(); struct sk_buff * c = alloc_skb(size, priority);
sk->wmem_alloc+= size; if (c) {
sti(); cli();
return(alloc_skb(size, priority)); sk->wmem_alloc+= size;
sti();
}
return c;
} }
DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n", DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n",
sk, size, force, priority)); sk, size, force, priority));
...@@ -1597,9 +1600,11 @@ sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority) ...@@ -1597,9 +1600,11 @@ 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) {
struct sk_buff *c = alloc_skb(size, priority); struct sk_buff *c = alloc_skb(size, priority);
cli(); if (c) {
if (c) sk->rmem_alloc += size; cli();
sti(); sk->rmem_alloc += size;
sti();
}
return(c); return(c);
} }
DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n", DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n",
......
...@@ -117,28 +117,29 @@ min(unsigned int a, unsigned int b) ...@@ -117,28 +117,29 @@ min(unsigned int a, unsigned int b)
} }
void static void __print_th(struct tcphdr *th)
print_th(struct tcphdr *th)
{ {
unsigned char *ptr; unsigned char *ptr;
if (inet_debug != DBG_TCP) return; printk("TCP header:\n");
printk(" source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
printk("TCP header:\n"); ntohs(th->source), ntohs(th->dest),
ptr =(unsigned char *)(th + 1); ntohl(th->seq), ntohl(th->ack_seq));
printk(" source=%d, dest=%d, seq =%ld, ack_seq = %ld\n", printk(" fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
ntohs(th->source), ntohs(th->dest), th->fin, th->syn, th->rst, th->psh, th->ack,
ntohl(th->seq), ntohl(th->ack_seq)); th->urg, th->res1, th->res2);
printk(" fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n", printk(" window = %d, check = %d urg_ptr = %d\n",
th->fin, th->syn, th->rst, th->psh, th->ack, ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
th->urg, th->res1, th->res2); printk(" doff = %d\n", th->doff);
printk(" window = %d, check = %d urg_ptr = %d\n", ptr =(unsigned char *)(th + 1);
ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr)); printk(" options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
printk(" doff = %d\n", th->doff); }
printk(" options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
}
static inline void print_th(struct tcphdr *th)
{
if (inet_debug == DBG_TCP)
__print_th(th);
}
/* This routine grabs the first thing off of a rcv queue. */ /* This routine grabs the first thing off of a rcv queue. */
static struct sk_buff * static struct sk_buff *
...@@ -616,6 +617,13 @@ static void tcp_send_skb(struct sock *sk, struct sk_buff *skb) ...@@ -616,6 +617,13 @@ static void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
/* We need to complete and send the packet. */ /* We need to complete and send the packet. */
tcp_send_check(skb->h.th, sk->saddr, sk->daddr, size, sk); tcp_send_check(skb->h.th, sk->saddr, sk->daddr, size, sk);
size -= 4*skb->h.th->doff;
if (skb->h.th->syn)
size++;
if (skb->h.th->fin)
size++;
sk->send_seq += size;
skb->h.seq = sk->send_seq; skb->h.seq = sk->send_seq;
if (after(sk->send_seq , sk->window_seq) || if (after(sk->send_seq , sk->window_seq) ||
(sk->retransmits && sk->timeout == TIME_WRITE) || (sk->retransmits && sk->timeout == TIME_WRITE) ||
...@@ -737,6 +745,10 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n"); ...@@ -737,6 +745,10 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
/* FIXME: */ /* FIXME: */
memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */ memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
/* hack-around */
if (after(sequence, sk->window_seq))
sequence = sk->window_seq;
/* swap the send and the receive. */ /* swap the send and the receive. */
t1->dest = th->source; t1->dest = th->source;
t1->source = th->dest; t1->source = th->dest;
...@@ -920,7 +932,6 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -920,7 +932,6 @@ tcp_write(struct sock *sk, unsigned char *from,
from += copy; from += copy;
copied += copy; copied += copy;
len -= copy; len -= copy;
sk->send_seq += copy;
} }
if ((skb->len - hdrlen) >= sk->mss || if ((skb->len - hdrlen) >= sk->mss ||
(flags & MSG_OOB) || (flags & MSG_OOB) ||
...@@ -943,14 +954,11 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -943,14 +954,11 @@ tcp_write(struct sock *sk, unsigned char *from,
* be queued for later rather than sent. * be queued for later rather than sent.
*/ */
copy = diff(sk->window_seq, sk->send_seq); copy = sk->window_seq - sk->send_seq;
/* what if max_window == 1? In that case max_window >> 1 is 0. if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)
* however in that case copy == max_window, so it's OK to use copy = sk->mss;
* the window */ if (copy > len)
if (copy < (sk->max_window >> 1)) copy = len;
copy = sk->mss;
copy = min(copy, sk->mss);
copy = min(copy, len);
/* We should really check the window here also. */ /* We should really check the window here also. */
send_tmp = NULL; send_tmp = NULL;
...@@ -1043,7 +1051,6 @@ tcp_write(struct sock *sk, unsigned char *from, ...@@ -1043,7 +1051,6 @@ tcp_write(struct sock *sk, unsigned char *from,
len -= copy; len -= copy;
skb->len += copy; skb->len += copy;
skb->free = 0; skb->free = 0;
sk->send_seq += copy;
if (send_tmp != NULL && sk->packets_out) { if (send_tmp != NULL && sk->packets_out) {
tcp_enqueue_partial(send_tmp, sk); tcp_enqueue_partial(send_tmp, sk);
...@@ -1136,7 +1143,10 @@ tcp_read_wakeup(struct sock *sk) ...@@ -1136,7 +1143,10 @@ tcp_read_wakeup(struct sock *sk)
t1 =(struct tcphdr *)(buff->data +tmp); t1 =(struct tcphdr *)(buff->data +tmp);
memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1)); memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
t1->seq = ntohl(sk->send_seq); if (after(sk->send_seq, sk->window_seq))
t1->seq = ntohl(sk->window_seq);
else
t1->seq = ntohl(sk->send_seq);
t1->ack = 1; t1->ack = 1;
t1->res1 = 0; t1->res1 = 0;
t1->res2 = 0; t1->res2 = 0;
...@@ -1613,13 +1623,13 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, ...@@ -1613,13 +1623,13 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
if(th->ack) if(th->ack)
{ {
t1->ack=0; t1->ack = 0;
t1->seq=th->ack_seq; t1->seq = th->ack_seq;
t1->ack_seq=0; t1->ack_seq = 0;
} }
else else
{ {
t1->ack=1; t1->ack = 1;
if(!th->syn) if(!th->syn)
t1->ack_seq=htonl(th->seq); t1->ack_seq=htonl(th->seq);
else else
...@@ -3049,75 +3059,60 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -3049,75 +3059,60 @@ tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
} }
/* This functions checks to see if the tcp header is actually acceptible. */ /* This functions checks to see if the tcp header is actually acceptable. */
static int static int
tcp_sequence(struct sock *sk, struct tcphdr *th, short len, tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
struct options *opt, unsigned long saddr, struct device *dev) struct options *opt, unsigned long saddr, struct device *dev)
{ {
/* unsigned long next_seq;
* This isn't quite right. sk->acked_seq could be more recent
* than sk->window. This is however close enough. We will accept
* slightly more packets than we should, but it should not cause
* problems unless someone is trying to forge packets.
*/
DPRINTF((DBG_TCP, "tcp_sequence(sk=%X, th=%X, len = %d, opt=%d, saddr=%X)\n",
sk, th, len, opt, saddr));
if (between(th->seq, sk->acked_seq, sk->acked_seq + sk->window)||
between(th->seq + len-(th->doff*4), sk->acked_seq + 1,
sk->acked_seq + sk->window) ||
(before(th->seq, sk->acked_seq) &&
after(th->seq + len -(th->doff*4), sk->acked_seq + sk->window))) {
return(1);
}
DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
/* next_seq = len - 4*th->doff;
* Send a reset if we get something not ours and we are /* if we have a zero window, we can't have any data in the packet.. */
* unsynchronized. Note: We don't do anything to our end. We if (next_seq && !sk->window)
* are just killing the bogus remote connection then we will goto ignore_it;
* connect again and it will work (with luck). next_seq += th->seq;
*/ if (th->syn)
next_seq++;
if(sk->state==TCP_SYN_SENT||sk->state==TCP_SYN_RECV)
{
tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
return(1);
}
/* /*
* If it's too far ahead, send an ack to let the * This isn't quite right. sk->acked_seq could be more recent
* other end know what we expect. * than sk->window. This is however close enough. We will accept
*/ * slightly more packets than we should, but it should not cause
if (after(th->seq, sk->acked_seq + sk->window)) { * problems unless someone is trying to forge packets.
if(!th->rst) */
tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
return(0);
}
#ifdef undef /* have we already seen all of this packet? */
/* if (!after(next_seq+1, sk->acked_seq))
* if we do this, we won't respond to keepalive packets, since those goto ignore_it;
* are slightly out of window, and we have to generate an ack /* or does it start beyond the window? */
* a late ack out still not to have a sequence number less than if (!before(th->seq, sk->acked_seq + sk->window + 1))
* one we've seen before. Berkeley doesn't seem to do this, but it's goto ignore_it;
* always hard to be sure.
*/
/* In case it's just a late ack, let it through. */
if (th->ack && len == (th->doff * 4) &&
after(th->seq, sk->acked_seq - 32767) &&
!th->fin && !th->syn) return(1);
#endif
if (!th->rst) { /* ok, at least part of this packet would seem interesting.. */
/* Try to resync things. */ return 1;
tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
}
return(0);
}
ignore_it:
DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
/*
* Send a reset if we get something not ours and we are
* unsynchronized. Note: We don't do anything to our end. We
* are just killing the bogus remote connection then we will
* connect again and it will work (with luck).
*/
if (sk->state==TCP_SYN_SENT || sk->state==TCP_SYN_RECV) {
tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
return 1;
}
if (th->rst)
return 0;
/* Try to resync things. */
tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
return 0;
}
int int
...@@ -3175,14 +3170,12 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n"); ...@@ -3175,14 +3170,12 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
return(0); return(0);
} }
th->seq = ntohl(th->seq);
/* See if we know about the socket. */ /* See if we know about the socket. */
if (sk == NULL) { if (sk == NULL) {
if (!th->rst) if (!th->rst)
{
th->seq = ntohl(th->seq);
/* So reset is always called with th->seq in host order */
tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255); tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
}
skb->sk = NULL; skb->sk = NULL;
kfree_skb(skb, FREE_READ); kfree_skb(skb, FREE_READ);
return(0); return(0);
...@@ -3196,8 +3189,6 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n"); ...@@ -3196,8 +3189,6 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
skb->saddr = daddr; skb->saddr = daddr;
skb->daddr = saddr; skb->daddr = saddr;
th->seq = ntohl(th->seq);
/* We may need to add it to the backlog here. */ /* We may need to add it to the backlog here. */
cli(); cli();
if (sk->inuse) { if (sk->inuse) {
...@@ -3317,12 +3308,11 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n"); ...@@ -3317,12 +3308,11 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
release_sock(sk); release_sock(sk);
return(0); return(0);
} }
if (th->ack) {
if (!tcp_ack(sk, th, saddr, len)) { if (th->ack && !tcp_ack(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ); kfree_skb(skb, FREE_READ);
release_sock(sk); release_sock(sk);
return(0); return(0);
}
} }
if (tcp_urg(sk, th, saddr, len)) { if (tcp_urg(sk, th, saddr, len)) {
...@@ -3684,10 +3674,8 @@ tcp_send_probe0(struct sock *sk) ...@@ -3684,10 +3674,8 @@ tcp_send_probe0(struct sock *sk)
* sends fin in a separate packet * sends fin in a separate packet
* syn, rst, had better be zero in original */ * syn, rst, had better be zero in original */
t1->ack = 1; t1->ack = 1;
t1->urg = 0; /* urgent pointer might be beyond this fragment */
t1->res2 = 0; t1->res2 = 0;
t1->window = ntohs(tcp_select_window(sk)/*sk->prot->rspace(sk)*/); t1->window = ntohs(tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
t1->urg_ptr = 0;
tcp_send_check(t1, sk->saddr, sk->daddr, len - hlen, sk); tcp_send_check(t1, sk->saddr, sk->daddr, len - hlen, sk);
/* Send it and free it. /* Send it and free it.
* This will prevent the timer from automatically being restarted. * This will prevent the timer from automatically being restarted.
......
...@@ -80,10 +80,7 @@ ...@@ -80,10 +80,7 @@
*/ */
static inline int before(unsigned long seq1, unsigned long seq2) static inline int before(unsigned long seq1, unsigned long seq2)
{ {
/* this inequality is strict. */ seq2 -= seq1+1;
if (seq1 == seq2)
return 0;
seq2 -= seq1;
return (seq2 < 65536); return (seq2 < 65536);
} }
...@@ -118,7 +115,6 @@ tcp_connected(const int state) ...@@ -118,7 +115,6 @@ tcp_connected(const int state)
extern struct proto tcp_prot; extern struct proto tcp_prot;
extern void print_th(struct tcphdr *);
extern void tcp_err(int err, unsigned char *header, unsigned long daddr, extern void tcp_err(int err, unsigned char *header, unsigned long daddr,
unsigned long saddr, struct inet_protocol *protocol); unsigned long saddr, struct inet_protocol *protocol);
extern void tcp_shutdown (struct sock *sk, int how); extern void tcp_shutdown (struct sock *sk, int how);
......
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