aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1994-02-18 14:54:02 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:33 -0400
commit42f89c5ded09dc700fbabdd6008c7781e99762e2 (patch)
tree94f70c69ae53701ff5d040f1ed34a1f257b17b13
parent2fd717bbd7af8cb1dfd2f00df621b945e55e16fb (diff)
downloadarchive-42f89c5ded09dc700fbabdd6008c7781e99762e2.tar.gz
ALPHA-pl15f
-rw-r--r--Configure1
-rw-r--r--Makefile2
-rw-r--r--drivers/char/psaux.c1
-rw-r--r--drivers/char/serial.c6
-rw-r--r--drivers/char/tty_ioctl.c18
-rw-r--r--drivers/net/3c507.c63
-rw-r--r--drivers/net/8390.c252
-rw-r--r--drivers/net/Space.c5
-rw-r--r--drivers/net/at1700.c48
-rw-r--r--drivers/net/atp.c10
-rw-r--r--drivers/net/eexpress.c90
-rw-r--r--drivers/net/hp.c28
-rw-r--r--drivers/net/lance.c31
-rw-r--r--drivers/net/ne.c8
-rw-r--r--drivers/net/slip.c1
-rw-r--r--drivers/net/smc-ultra.c4
-rw-r--r--fs/binfmt_elf.c347
-rw-r--r--fs/buffer.c4
-rw-r--r--fs/proc/array.c2
-rw-r--r--include/linux/if_ether.h35
-rw-r--r--include/linux/tty.h2
-rw-r--r--ipc/util.c27
-rw-r--r--kernel/ksyms.sh2
-rw-r--r--kernel/traps.c9
-rw-r--r--net/inet/ip.c25
-rw-r--r--net/inet/skbuff.h3
-rw-r--r--net/inet/sock.c5
-rw-r--r--net/inet/sock.h3
-rw-r--r--net/inet/tcp.c300
-rw-r--r--net/inet/tcp.h3
-rw-r--r--zBoot/Makefile2
31 files changed, 766 insertions, 571 deletions
diff --git a/Configure b/Configure
index 77c8445..b3c4cc8 100644
--- a/Configure
+++ b/Configure
@@ -160,6 +160,7 @@ function int () {
CONFIG=.config~
CONFIG_H=include/linux/autoconf.h
+trap "rm -f $CONFIG $CONFIG_H config.new ; exit 1" 1 2
#
# Make sure we start out with a clean slate.
diff --git a/Makefile b/Makefile
index 85f0f4c..18c648b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 0.99
PATCHLEVEL = 15
-ALPHA = e
+ALPHA = f
all: Version zImage
diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c
index da133b3..3944c22 100644
--- a/drivers/char/psaux.c
+++ b/drivers/char/psaux.c
@@ -442,7 +442,6 @@ unsigned long psaux_init(unsigned long kmem_start)
int qp_found = 0;
#ifdef CONFIG_82C710_MOUSE
- printk("Probing 82C710 mouse port device.\n");
if ((qp_found = probe_qp())) {
printk("82C710 type pointing device detected -- driver installed.\n");
/* printk("82C710 address = %x (should be 0x310)\n", qp_data); */
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index 88aa55b..136be8f 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -1528,11 +1528,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
tty->hw_stopped = 0;
if (info->flags & ASYNC_INITIALIZED) {
rs_start(tty);
- /*
- * XXX There should be a timeout added to
- * wait_until_sent, eventually. TYT 1/19/94
- */
- wait_until_sent(tty);
+ wait_until_sent(tty, 6000); /* 60 seconds timeout */
} else
flush_output(tty);
flush_input(tty);
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 3895262..1aec5ba 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -82,7 +82,7 @@ void flush_output(struct tty_struct * tty)
}
}
-void wait_until_sent(struct tty_struct * tty)
+void wait_until_sent(struct tty_struct * tty, int timeout)
{
struct wait_queue wait = { current, NULL };
@@ -91,7 +91,11 @@ void wait_until_sent(struct tty_struct * tty)
return;
add_wait_queue(&tty->write_q.proc_list, &wait);
current->counter = 0; /* make us low-priority */
- while (1) {
+ if (timeout)
+ current->timeout = timeout + jiffies;
+ else
+ current->timeout = (unsigned) -1;
+ do {
current->state = TASK_INTERRUPTIBLE;
if (current->signal & ~current->blocked)
break;
@@ -99,7 +103,7 @@ void wait_until_sent(struct tty_struct * tty)
if (EMPTY(&tty->write_q))
break;
schedule();
- }
+ } while (current->timeout);
current->state = TASK_RUNNING;
remove_wait_queue(&tty->write_q.proc_list, &wait);
}
@@ -297,7 +301,7 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
return 0; /* We are already in the desired discipline */
/* Shutdown the current discipline. */
- wait_until_sent(tty);
+ wait_until_sent(tty, 0);
flush_input(tty);
if (ldiscs[tty->disc].close)
ldiscs[tty->disc].close(tty);
@@ -379,7 +383,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
if (cmd == TCSETSF || cmd == TCSETSW) {
if (cmd == TCSETSF)
flush_input(termios_tty);
- wait_until_sent(termios_tty);
+ wait_until_sent(termios_tty, 0);
}
return set_termios(termios_tty, (struct termios *) arg,
termios_dev);
@@ -394,7 +398,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
if (cmd == TCSETAF || cmd == TCSETAW) {
if (cmd == TCSETAF)
flush_input(termios_tty);
- wait_until_sent(termios_tty);
+ wait_until_sent(termios_tty, 0);
}
return set_termio(termios_tty, (struct termio *) arg,
termios_dev);
@@ -642,7 +646,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
retval = check_change(tty, dev);
if (retval)
return retval;
- wait_until_sent(tty);
+ wait_until_sent(tty, 0);
if (!tty->ioctl)
return 0;
tty->ioctl(tty, file, cmd, arg);
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index ba53e06..8ee16f6 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -11,6 +11,8 @@
Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
+ Mark Salazar <leslie@access.digex.net> made the changes for cards with
+ only 16K packet buffers.
Things remaining to do:
Verify that the tx and rx buffers don't have fencepost errors.
@@ -19,7 +21,7 @@
*/
static char *version =
- "3c507.c:v0.03 10/27/93 Donald Becker (becker@super.org)\n";
+ "3c507.c:v0.99-15f 2/17/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
@@ -145,6 +147,17 @@ struct net_local {
#define iSCB_CBL 0xC /* Command BLock offset. */
#define iSCB_RFA 0xE /* Rx Frame Area offset. */
+/* Since the 3c507 maps the shared memory window so that the last byte is
+ at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or
+ 48K cooresponding to window sizes of 64K, 48K, 32K and 16K respectively.
+ We can account for this be setting the 'SBC Base' entry in the ISCP table
+ below for all the 16 bit offset addresses, and also adding the 'SCB Base'
+ value to all 24 bit physical addresses (in the SCP table and the TX and RX
+ Buffer Descriptors).
+ -Mark
+ */
+#define SCB_BASE ((unsigned)64*1024 - (dev->mem_end - dev->mem_start))
+
/*
What follows in 'init_words[]' is the "program" that is downloaded to the
82586 memory. It's mostly tables and command blocks, and starts at the
@@ -192,7 +205,7 @@ struct net_local {
The Tx command chain and buffer list is setup as follows:
A Tx command table, with the data buffer pointing to...
A Tx data buffer descriptor. The packet is in a single buffer, rather than
- chaining together several smaller buffers.
+ chaining together several smaller buffers.
A NoOp command, which initially points to itself,
And the packet data.
@@ -213,13 +226,17 @@ struct net_local {
*/
-short init_words[] = {
+unsigned short init_words[] = {
+ /* System Configuration Pointer (SCP). */
0x0000, /* Set bus size to 16 bits. */
- 0x0000,0x0000, /* Set control mailbox (SCB) addr. */
- 0,0, /* pad to 0x000000. */
+ 0,0, /* pad words. */
+ 0x0000,0x0000, /* ISCP phys addr, set in init_82586_mem(). */
+
+ /* Intermediate System Configuration Pointer (ISCP). */
0x0001, /* Status word that's cleared when init is done. */
0x0008,0,0, /* SCB offset, (skip, skip) */
+ /* System Control Block (SCB). */
0,0xf000|RX_START|CUC_START, /* SCB status and cmd. */
CONFIG_CMD, /* Command list pointer, points to Configure. */
RX_BUF_START, /* Rx block list. */
@@ -270,11 +287,11 @@ void init_82586_mem(struct device *dev);
/* Check for a network adaptor of this type, and return '0' iff one exists.
- If dev->base_addr == 0, probe all likely locations.
- If dev->base_addr == 1, always return failure.
- If dev->base_addr == 2, (detachable devices only) alloate space for the
- device and return success.
- */
+ If dev->base_addr == 0, probe all likely locations.
+ If dev->base_addr == 1, always return failure.
+ If dev->base_addr == 2, (detachable devices only) alloate space for the
+ device and return success.
+ */
int
el16_probe(struct device *dev)
{
@@ -369,9 +386,6 @@ int el16_probe1(struct device *dev, short ioaddr)
size = ((mem_config & 3) + 1) << 14;
base = 0x0c0000 + ( (mem_config & 0x18) << 12);
}
- if (size != 0x10000)
- printk("%s: Warning, this version probably only works with 64K of"
- "shared memory.\n", dev->name);
dev->mem_start = base;
dev->mem_end = base + size;
}
@@ -538,9 +552,9 @@ el16_interrupt(int reg_ptr)
status = shmem[iSCB_STATUS>>1];
- if (net_debug > 4) {
+ if (net_debug > 4) {
printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
- }
+ }
/* Disable the 82586's input to the interrupt line. */
outb(0x80, ioaddr + MISC_CTRL);
@@ -661,6 +675,7 @@ init_rx_bufs(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
unsigned short *write_ptr;
+ unsigned short SCB_base = SCB_BASE;
int cur_rxbuf = lp->rx_head = RX_BUF_START;
@@ -683,7 +698,7 @@ init_rx_bufs(struct device *dev)
*write_ptr++ = 0x0000; /* Buffer: Actual count */
*write_ptr++ = -1; /* Buffer: Next (none). */
- *write_ptr++ = cur_rxbuf + 0x20; /* Buffer: Address low */
+ *write_ptr++ = cur_rxbuf + 0x20 + SCB_base; /* Buffer: Address low */
*write_ptr++ = 0x0000;
/* Finally, the number of bytes in the buffer. */
*write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20;
@@ -712,12 +727,13 @@ init_82586_mem(struct device *dev)
and hold the 586 in reset during the memory initialization. */
outb(0x20, ioaddr + MISC_CTRL);
+ /* Fix the ISCP address and base. */
+ init_words[3] = SCB_BASE;
+ init_words[7] = SCB_BASE;
+
/* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
-#ifdef old
- memcpy((void*)dev->mem_start+0xfff6, init_words, 10);
-#else
memcpy((void*)dev->mem_end-10, init_words, 10);
-#endif
+
/* Write the words at 0x0000. */
memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10);
@@ -776,7 +792,7 @@ hardware_send_packet(struct device *dev, void *buf, short length)
/* Output the data buffer descriptor. */
*write_ptr++ = length | 0x8000; /* Byte count parameter. */
*write_ptr++ = -1; /* No next data buffer. */
- *write_ptr++ = tx_block+22; /* Buffer follows the NoOp command. */
+ *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */
*write_ptr++ = 0x0000; /* Buffer address high bits (always zero). */
/* Output the Loop-back NoOp command. */
@@ -796,10 +812,10 @@ hardware_send_packet(struct device *dev, void *buf, short length)
if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
lp->tx_head = TX_BUF_START;
- if (net_debug > 4) {
+ if (net_debug > 4) {
printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
dev->name, ioaddr, length, tx_block, lp->tx_head);
- }
+ }
if (lp->tx_head != lp->tx_reap)
dev->tbusy = 0;
@@ -893,6 +909,7 @@ el16_rx(struct device *dev)
* version-control: t
* kept-new-versions: 5
* tab-width: 4
+ * c-indent-level: 4
* End:
*/
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 9c896cc..024568e 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -8,22 +8,21 @@
incorporated herein by reference.
This is the chip-specific code for many 8390-based ethernet adaptors.
+ This is not a complete driver, it must be combined with board-specific
+ code such as ne.c, wd.c, 3c503.c, etc.
The Author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
static char *version =
- "8390.c:v0.99-13f 10/18/93 Donald Becker (becker@super.org)\n";
+ "8390.c:v0.99-15e 2/16/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
/*
Braindamage remaining:
-
- Ethernet devices should use a chr_drv device interface, with ioctl()s to
- configure the card, bring the interface up or down, allow access to
- statistics, and maybe read() and write() access to raw packets.
- This won't be done until after Linux 1.00.
+ Much of this code should be cleaned up post-1.00, but it has been
+ extensively beta tested in the current form.
Sources:
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -59,11 +58,22 @@ static char *version =
#include "8390.h"
-#ifndef HAVE_ALLOC_SKB
-#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
-#define kfree_skbmem(addr, size) kfree_s(addr,size)
-#endif
-
+/* These are the operational function interfaces to board-specific
+ routines.
+ void reset_8390(struct device *dev)
+ Resets the board associated with DEV, including a hardware reset of
+ the 8390. This is only called when there is a transmit timeout, and
+ it is always followed by 8390_init().
+ void block_output(struct device *dev, int count, const unsigned char *buf,
+ int start_page)
+ Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
+ "page" value uses the 8390's 256-byte pages.
+ int block_input(struct device *dev, int count, char *buf, int ring_offset)
+ Read COUNT bytes from the packet buffer into BUF. Start reading from
+ RING_OFFSET, the address as the 8390 sees it. The first read will
+ always be the 4 byte, page aligned 8390 header. *If* there is a
+ subsequent read, it will be of the rest of the packet.
+*/
#define ei_reset_8390 (ei_local->reset_8390)
#define ei_block_output (ei_local->block_output)
#define ei_block_input (ei_local->block_input)
@@ -75,14 +85,14 @@ int ei_debug = EI_DEBUG;
int ei_debug = 1;
#endif
-/* Max number of packets received at one Intr. */
-/*static int high_water_mark = 0;*/
+/* Max number of packets received at one Intr.
+ Current this may only be examined by a kernel debugger. */
+static int high_water_mark = 0;
/* Index to functions. */
-/* Put in the device structure. */
-int ei_open(struct device *dev);
-/* Dispatch from interrupts. */
-void ei_interrupt(int reg_ptr);
+int ei_open(struct device *dev); /* Put into the device structure. */
+void ei_interrupt(int reg_ptr); /* Installed as the interrupt handler. */
+
static void ei_tx_intr(struct device *dev);
static void ei_receive(struct device *dev);
static void ei_rx_overrun(struct device *dev);
@@ -107,7 +117,7 @@ int ei_open(struct device *dev)
if ( ! ei_local) {
printk("%s: Opening a non-existent physical device\n", dev->name);
- return 1; /* ENXIO would be more accurate. */
+ return ENXIO;
}
irq2dev_map[dev->irq] = dev;
@@ -128,31 +138,36 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
int e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int length, send_length;
- int tmp_tbusy; /* we must lock dev_tint in dev.c with dev->t_busy =1 */
- /* because on a slow pc a quasi endless loop can appear */
+ /* We normally shouldn't be called if dev->tbusy is set, but the
+ existing code does anyway.
+ If it has been too long (> 100 or 150ms.) since the last Tx we assume
+ the board has died and kick it. */
+
if (dev->tbusy) { /* Do timeouts, just like the 8003 driver. */
int txsr = inb(e8390_base+EN0_TSR), isr;
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5 || (tickssofar < 15 && ! (txsr & ENTSR_PTX))) {
+ if (tickssofar < 10 || (tickssofar < 15 && ! (txsr & ENTSR_PTX))) {
return 1;
}
isr = inb(e8390_base+EN0_ISR);
printk("%s: transmit timed out, TX status %#2x, ISR %#2x.\n",
dev->name, txsr, isr);
- /* It's possible to check for an IRQ conflict here.
- I may have to do that someday. */
+ /* Does the 8390 thinks it has posted an interrupt? */
if (isr)
- printk("%s: Possible IRQ conflict on IRQ%d?", dev->name, dev->irq);
- else
+ printk("%s: Possible IRQ conflict on IRQ%d?\n", dev->name, dev->irq);
+ else {
+ /* The 8390 probably hasn't gotten on the cable yet. */
printk("%s: Possible network cable problem?\n", dev->name);
- /* It futile, but try to restart it anyway. */
+ ei_local->interface_num ^= 1; /* Try a different xcvr. */
+ }
+ /* Try to restart the card. Perhaps the user has fixed something. */
ei_reset_8390(dev);
NS8390_init(dev, 1);
- printk("\n");
+ dev->trans_start = jiffies;
}
- /* This is new: it means some higher layer thinks we've missed an
+ /* Sending a NULL skb means some higher layer thinks we've missed an
tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
itself. */
if (skb == NULL) {
@@ -167,28 +182,22 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
}
skb->arp=1;
+ length = skb->len;
if (skb->len <= 0)
return 0;
- length = skb->len;
- send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
- /* Turn off interrupts so that we can put the packet out safely. */
- cli();
- if (dev->interrupt || ei_local->irqlock) {
- /* We should never get here during an interrupt after 0.99.4. */
- sti();
- if (ei_debug > 2)
- printk("%s: Attempt to reenter critical zone%s.\n",
- dev->name, ei_local->irqlock ? " during interrupt" : "");
+
+ /* Block a timer-based transmit from overlapping. */
+ if (set_bit(0, (void*)&dev->tbusy) != 0) {
+ printk("%s: Transmitter access conflict.\n", dev->name);
return 1;
- }
+ }
+
/* Mask interrupts from the ethercard. */
outb(0x00, e8390_base + EN0_IMR);
-
- /* Atomically lock out dev.c:dev_tint(). */
- tmp_tbusy = set_bit(0, (void*)&dev->tbusy);
-
ei_local->irqlock = 1;
- sti();
+
+ send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
+
if (ei_local->pingpong) {
int output_page;
if (ei_local->tx1 == 0) {
@@ -205,23 +214,19 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
dev->name, ei_local->tx1, ei_local->lasttx,
ei_local->txing);
- } else {
- /* We can get to here if we get an rx interrupt and queued
- a tx packet just before masking 8390 irqs above. */
- if (ei_debug > 2)
+ } else { /* We should never get here. */
+ if (ei_debug)
printk("%s: No packet buffer space for ping-pong use.\n",
dev->name);
- cli();
ei_local->irqlock = 0;
- dev->tbusy = tmp_tbusy;
+ dev->tbusy = 1;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
- sti();
return 1;
}
- dev->trans_start = jiffies;
ei_block_output(dev, length, skb->data, output_page);
if (! ei_local->txing) {
NS8390_trigger_send(dev, send_length, output_page);
+ dev->trans_start = jiffies;
if (output_page == ei_local->tx_start_page)
ei_local->tx1 = -1, ei_local->lasttx = -1;
else
@@ -229,25 +234,22 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
ei_local->txing = 1;
} else
ei_local->txqueue++;
- if (ei_local->tx1 && ei_local->tx2)
- tmp_tbusy = 1;
- } else {
- dev->trans_start = jiffies;
- ei_block_output(dev, length, skb->data,
- ei_local->tx_start_page);
+
+ dev->tbusy = (ei_local->tx1 && ei_local->tx2);
+ } else { /* No pingpong, just a single Tx buffer. */
+ ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
- tmp_tbusy = 1;
- } /* PINGPONG */
+ dev->trans_start = jiffies;
+ dev->tbusy = 1;
+ }
+ /* Turn 8390 interrupts back on. */
+ ei_local->irqlock = 0;
+ outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
if (skb->free)
kfree_skb (skb, FREE_WRITE);
- /* Turn 8390 interrupts back on. */
- cli();
- outb_p(ENISR_ALL, e8390_base + EN0_IMR);
- ei_local->irqlock = 0;
- dev->tbusy=tmp_tbusy;
- sti();
return 0;
}
@@ -289,7 +291,7 @@ void ei_interrupt(int reg_ptr)
/* !!Assumption!! -- we stay in page 0. Don't break this. */
while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
- && ++boguscount < 20) {
+ && ++boguscount < 5) {
if (interrupts & ENISR_RDC) {
/* Ack meaningless DMA complete. */
outb_p(ENISR_RDC, e8390_base + EN0_ISR);
@@ -374,24 +376,19 @@ static void ei_tx_intr(struct device *dev)
ei_local->txing = 0;
dev->tbusy = 0;
}
-
- /* Do the statistics _after_ we start the next TX. */
+
+ /* Minimize Tx latency: update the statistics after we restart TXing. */
+ if (status & ENTSR_COL) ei_local->stat.collisions++;
if (status & ENTSR_PTX)
ei_local->stat.tx_packets++;
- else
+ else {
ei_local->stat.tx_errors++;
- if (status & ENTSR_COL)
- ei_local->stat.collisions++;
- if (status & ENTSR_ABT)
- ei_local->stat.tx_aborted_errors++;
- if (status & ENTSR_CRS)
- ei_local->stat.tx_carrier_errors++;
- if (status & ENTSR_FU)
- ei_local->stat.tx_fifo_errors++;
- if (status & ENTSR_CDH)
- ei_local->stat.tx_heartbeat_errors++;
- if (status & ENTSR_OWC)
- ei_local->stat.tx_window_errors++;
+ if (status & ENTSR_ABT) ei_local->stat.tx_aborted_errors++;
+ if (status & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
+ if (status & ENTSR_FU) ei_local->stat.tx_fifo_errors++;
+ if (status & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
+ if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++;
+ }
mark_bh (INET_BH);
}
@@ -403,11 +400,11 @@ static void ei_receive(struct device *dev)
int e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int rxing_page, this_frame, next_frame, current_offset;
- int boguscount = 0;
+ int rx_pkt_count = 0;
struct e8390_pkt_hdr rx_frame;
int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
- while (++boguscount < 10) {
+ while (++rx_pkt_count < 10) {
int pkt_len;
/* Get the rx page (incoming packet pointer). */
@@ -420,8 +417,9 @@ static void ei_receive(struct device *dev)
if (this_frame >= ei_local->stop_page)
this_frame = ei_local->rx_start_page;
- /* Someday we'll omit the previous step, iff we never get this message.*/
- if (ei_debug > 0 && this_frame != ei_local->current_page)
+ /* Someday we'll omit the previous, iff we never get this message.
+ (There is at least one clone claimed to have a problem.) */
+ if (ei_debug > 0 && this_frame != ei_local->current_page)
printk("%s: mismatched read page pointers %2x vs %2x.\n",
dev->name, this_frame, ei_local->current_page);
@@ -439,46 +437,23 @@ static void ei_receive(struct device *dev)
/* Check for bogosity warned by 3c503 book: the status byte is never
written. This happened a lot during testing! This code should be
cleaned up someday. */
- if ( rx_frame.next != next_frame
+ if (rx_frame.next != next_frame
&& rx_frame.next != next_frame + 1
&& rx_frame.next != next_frame - num_rx_pages
&& rx_frame.next != next_frame + 1 - num_rx_pages) {
-#ifndef EI_DEBUG
ei_local->current_page = rxing_page;
outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
+ ei_local->stat.rx_errors++;
continue;
-#else
- static int last_rx_bogosity = -1;
- printk("%s: bogus packet header, status=%#2x nxpg=%#2x sz=%#x (at %#4x)\n",
- dev->name, rx_frame.status, rx_frame.next, rx_frame.count,
- current_offset);
-
- if (ei_local->stat.rx_packets != last_rx_bogosity) {
- /* Maybe we can avoid resetting the chip... empty the packet ring. */
- ei_local->current_page = rxing_page;
- printk("%s: setting next frame to %#2x (nxt=%#2x, rx_frm.nx=%#2x rx_frm.stat=%#2x).\n",
- dev->name, ei_local->current_page, next_frame,
- rx_frame.next, rx_frame.status);
- last_rx_bogosity = ei_local->stat.rx_packets;
- outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
- continue;
- } else {
- /* Oh no Mr Bill! Last ditch error recovery. */
- printk("%s: recovery failed, resetting at packet #%d..",
- dev->name, ei_local->stat.rx_packets);
- sti();
- ei_reset_8390(dev);
- NS8390_init(dev, 1);
- printk("restarting.\n");
- return;
- }
-#endif /* EI8390_NOCHECK */
}
-
- if ((pkt_len < 46 || pkt_len > 1535) && ei_debug)
- printk("%s: bogus packet size, status=%#2x nxpg=%#2x size=%#x\n",
- dev->name, rx_frame.status, rx_frame.next, rx_frame.count);
- if ((rx_frame.status & 0x0F) == ENRSR_RXOK) {
+
+ if (pkt_len < 60 || pkt_len > 1518) {
+ if (ei_debug)
+ printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
+ dev->name, rx_frame.count, rx_frame.status,
+ rx_frame.next);
+ ei_local->stat.rx_errors++;
+ } else if ((rx_frame.status & 0x0F) == ENRSR_RXOK) {
int sksize = sizeof(struct sk_buff) + pkt_len;
struct sk_buff *skb;
@@ -495,44 +470,39 @@ static void ei_receive(struct device *dev)
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb->data' points to the start of sk_buff data area. */
ei_block_input(dev, pkt_len, (char *) skb->data,
current_offset + sizeof(rx_frame));
-#ifdef HAVE_NETIF_RX
netif_rx(skb);
-#else
- skb->lock = 0;
- if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev)) {
- kfree_skbmem(skb, sksize);
- lp->stats.rx_dropped++;
- break;
- }
-#endif
ei_local->stat.rx_packets++;
}
} else {
int errs = rx_frame.status;
if (ei_debug)
- printk("%s: bogus packet, status=%#2x nxpg=%#2x size=%d\n",
- dev->name, rx_frame.status, rx_frame.next, rx_frame.count);
+ printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+ dev->name, rx_frame.status, rx_frame.next,
+ rx_frame.count);
if (errs & ENRSR_FO)
ei_local->stat.rx_fifo_errors++;
}
next_frame = rx_frame.next;
- /* This should never happen, it's here for debugging. */
+ /* This _should_ never happen: it's here for avoiding bad clones. */
if (next_frame >= ei_local->stop_page) {
- printk("%s: next frame inconsistency, %#2x..", dev->name, next_frame);
+ printk("%s: next frame inconsistency, %#2x..", dev->name,
+ next_frame);
next_frame = ei_local->rx_start_page;
}
- ei_local->current_page += 1 + ((pkt_len+4)>>8);
ei_local->current_page = next_frame;
outb(next_frame-1, e8390_base+EN0_BOUNDARY);
}
/* If any worth-while packets have been received, dev_rint()
has done a mark_bh(INET_BH) for us and will work on them
when we get to the bottom-half routine. */
-
+
+ /* Record the maximum Rx packet queue. */
+ if (rx_pkt_count > high_water_mark)
+ high_water_mark = rx_pkt_count;
+
/* Bug alert! Reset ENISR_OVER to avoid spurious overruns! */
outb_p(ENISR_RX+ENISR_RX_ERR+ENISR_OVER, e8390_base+EN0_ISR);
return;
@@ -553,19 +523,20 @@ static void ei_rx_overrun(struct device *dev)
printk("%s: Receiver overrun.\n", dev->name);
ei_local->stat.rx_over_errors++;
- /* The we.c driver does dummy = inb_p( RBCR[01] ); at this point.
+ /* The old Biro driver does dummy = inb_p( RBCR[01] ); at this point.
It might mean something -- magic to speed up a reset? A 8390 bug?*/
- /* Wait for reset in case the NIC is doing a tx or rx. This could take up to
- 1.5msec, but we have no way of timing something in that range. The 'jiffies'
- are just a sanity check. */
+ /* Wait for the reset to complete. This should happen almost instantly,
+ but could take up to 1.5msec in certain rare instances. There is no
+ easy way of timing something in that range, so we use 'jiffies' as
+ a sanity check. */
while ((inb_p(e8390_base+EN0_ISR) & ENISR_RESET) == 0)
if (jiffies - reset_start_time > 1) {
printk("%s: reset did not complete at ei_rx_overrun.\n",
dev->name);
NS8390_init(dev, 1);
return;
- };
+ }
/* Remove packets right away. */
ei_receive(dev);
@@ -751,6 +722,7 @@ static void NS8390_trigger_send(struct device *dev, unsigned int length,
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 8390.c"
* version-control: t
* kept-new-versions: 5
+ * c-indent-level: 4
* tab-width: 4
* End:
*/
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index fc70286..dd53835 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -145,8 +145,9 @@ static struct device atp_dev = {
#ifndef ETH0_IRQ
# define ETH0_IRQ 0
#endif
-/* "eth0" defaults to autoprobe, other use a base of "-0x20", "don't probe".
- Enable these with boot-time setup. 0.99pl13+ can optionally autoprobe. */
+/* "eth0" defaults to autoprobe (== 0), other use a base of 0xffe0 (== -0x20),
+ which means "don't probe". These entries exist to only to provide empty
+ slots which may be enabled at boot-time. */
static struct device eth3_dev = {
"eth3", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index cfc5922..288693b 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -12,13 +12,16 @@
*/
static char *version =
- "at1700.c:v0.03 11/16/93 Donald Becker (becker@super.org)\n";
+ "at1700.c:v0.05 2/9/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
/*
Sources:
The Fujitsu MB86695 datasheet.
+
+ After this driver was written, ATI provided their EEPROM configuration
+ code header file. Thanks to Gerry Sockins of ATI.
*/
#include <linux/kernel.h>
@@ -30,12 +33,12 @@ static char *version =
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/malloc.h>
+#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <errno.h>
-#include <memory.h>
#include "dev.h"
#include "eth.h"
@@ -142,24 +145,28 @@ at1700_probe(struct device *dev)
for (port = &ports[0]; *port; port++) {
int ioaddr = *port;
-#ifdef HAVE_PORTRESERVE
if (check_region(ioaddr, 32))
continue;
-#endif
- if (inw(ioaddr) != 0x0000)
- continue;
if (at1700_probe1(dev, ioaddr) == 0)
return 0;
}
- return ENODEV; /* ENODEV would be more accurate. */
+ return ENODEV;
}
+/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
+ "signature", the default bit pattern after a reset. This *doesn't* work --
+ there is no way to reset the bus interface without a complete power-cycle!
+
+ It turns out that ATI came to the same conclusion I did: the only thing
+ that can be done is checking a few bits and then diving right into an
+ EEPROM read. */
+
int at1700_probe1(struct device *dev, short ioaddr)
{
- unsigned short signature[4] = {0x0000, 0xffff, 0x41f6, 0xefb6};
- unsigned short signature_invalid[4] = {0x0000, 0xffff, 0x00f0, 0x2f00};
- char irqmap[4] = {3, 4, 5, 9};
+ unsigned short signature[4] = {0xffff, 0xffff, 0x7ff7, 0xff5f};
+ unsigned short signature_invalid[4] = {0xffff, 0xffff, 0x7ff7, 0xdf0f};
+ char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
unsigned short *station_address = (unsigned short *)dev->dev_addr;
unsigned int i, irq;
@@ -168,18 +175,21 @@ int at1700_probe1(struct device *dev, short ioaddr)
*/
for (i = 0; i < 4; i++)
if ((inw(ioaddr + 2*i) | signature_invalid[i]) != signature[i]) {
- if (net_debug > 1)
+ if (net_debug > 2)
printk("AT1700 signature match failed at %d (%04x vs. %04x)\n",
i, inw(ioaddr + 2*i), signature[i]);
return -ENODEV;
}
-#ifdef HAVE_PORTRESERVE
+ if (read_eeprom(ioaddr, 4) != 0x0000
+ || read_eeprom(ioaddr, 5) & 0x00ff != 0x00F4)
+ return -ENODEV;
+
/* Grab the region so that we can find another board if the IRQ request
fails. */
snarf_region(ioaddr, 32);
-#endif
- irq = irqmap[ read_eeprom(ioaddr, 0) >> 14 ];
+ irq = irqmap[(read_eeprom(ioaddr, 12)&0x04)
+ | (read_eeprom(ioaddr, 0)>>14)];
/* Snarf the interrupt vector now. */
if (request_irq(irq, &net_interrupt)) {
@@ -402,7 +412,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
@@ -415,7 +425,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
+ unsigned char *buf = (void *)(skb+1);
if (net_debug > 4)
printk("%s: Transmitting a packet of length %d.\n", dev->name,
@@ -551,14 +561,14 @@ net_rx(struct device *dev)
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb->data' points to the start of sk_buff data area. */
- insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1);
+ /* 'skb+1' points to the start of sk_buff data area. */
+ insw(ioaddr + DATAPORT, (void *)(skb+1), (pkt_len + 1) >> 1);
if (net_debug > 5) {
int i;
printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
for (i = 0; i < 14; i++)
- printk(" %02x", skb->data[i]);
+ printk(" %02x", ((unsigned char*)(skb + 1))[i]);
printk(".\n");
}
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index d86dc82..e99d024 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -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
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
@@ -490,7 +490,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
+ unsigned char *buf = (void *)(skb+1);
int flags;
/* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
@@ -686,11 +686,11 @@ static void net_rx(struct device *dev)
skb->len = pkt_len;
skb->dev = dev;
- /* 'skb->data' points to the start of sk_buff data area. */
- read_block(ioaddr, pkt_len, skb->data, dev->if_port);
+ /* 'skb+1' points to the start of sk_buff data area. */
+ read_block(ioaddr, pkt_len, (unsigned char *)(skb + 1), dev->if_port);
if (net_debug > 6) {
- unsigned char *data = skb->data;
+ unsigned char *data = (unsigned char *)(skb + 1);
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[6], data[7], data[8], data[9], data[10], data[11],
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index dff4238..d658e50 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -19,7 +19,7 @@
*/
static char *version =
- "eexpress.c:v0.06 10/27/93 Donald Becker (becker@super.org)\n";
+ "eexpress.c:v0.07 1/19/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
@@ -154,7 +154,7 @@ struct net_local {
#define ASIC_RESET 0x40
#define _586_RESET 0x80
-/* Offsets into the System Control Block structure. */
+/* Offsets to elements of the System Control Block structure. */
#define SCB_STATUS 0xc008
#define SCB_CMD 0xc00A
#define CUC_START 0x0100
@@ -175,8 +175,8 @@ struct net_local {
program space than initializing the individual tables, and I feel it's much
cleaner.
- The databook is particularly useless for the first two structures, I had
- to use the Crynwr driver as an example.
+ The databook is particularly useless for the first two structures; they are
+ completely undocumented. I had to use the Crynwr driver as an example.
The memory setup is as follows:
*/
@@ -194,17 +194,18 @@ struct net_local {
#define TX_BUF_START 0x0100
#define NUM_TX_BUFS 4
-#define TX_BUF_SIZE (1518+14+20+16) /* packet+header+TBD */
+#define TX_BUF_SIZE 0x0680 /* packet+header+TBD+extra (1518+14+20+16) */
+#define TX_BUF_END 0x2000
#define RX_BUF_START 0x2000
#define RX_BUF_SIZE (0x640) /* packet+header+RBD+extra */
-#define RX_BUF_END 0x8000
+#define RX_BUF_END 0x4000
/*
That's it: only 86 bytes to set up the beast, including every extra
command available. The 170 byte buffer at DUMP_DATA is shared between the
Dump command (called only by the diagnostic program) and the SetMulticastList
- command.
+ command.
To complete the memory setup you only have to write the station address at
SA_OFFSET and create the Tx & Rx buffer lists.
@@ -326,6 +327,7 @@ express_probe(struct device *dev)
#ifdef notdef
for (i = 16; i > 0; i--)
sum += inb(id_addr);
+ printk("EtherExpress ID checksum is %04x.\n", sum);
#else
for (i = 4; i > 0; i--) {
short id_val = inb(id_addr);
@@ -353,7 +355,7 @@ int eexp_probe1(struct device *dev, short ioaddr)
station_addr[1] = read_eeprom(ioaddr, 3);
station_addr[2] = read_eeprom(ioaddr, 4);
- /* Check the first three octets of the S.A. for the manufactor's code. */
+ /* Check the first three octets of the S.A. for the manufactor's code. */
if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) {
printk(" rejected (invalid address %04x%04x%04x).\n",
station_addr[2], station_addr[1], station_addr[0]);
@@ -511,7 +513,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev)
/* For ethernet, fill in the header. This should really be done by a
higher level, rather than duplicated for each ethernet adaptor. */
- if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
@@ -523,7 +525,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
+ unsigned char *buf = (void *)(skb+1);
/* Disable the 82586's input to the interrupt line. */
outb(irqrmap[dev->irq], ioaddr + SET_IRQ);
@@ -551,8 +553,8 @@ eexp_interrupt(int reg_ptr)
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
int ioaddr, status, boguscount = 0;
- short ack_cmd = 0;
-
+ short ack_cmd;
+
if (dev == NULL) {
printk ("net_interrupt(): irq %d for unknown device.\n", irq);
return;
@@ -595,7 +597,7 @@ eexp_interrupt(int reg_ptr)
if (net_debug > 5)
printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
lp->tx_reap += TX_BUF_SIZE;
- if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
+ if (lp->tx_reap > TX_BUF_END - TX_BUF_SIZE)
lp->tx_reap = TX_BUF_START;
if (++boguscount > 4)
break;
@@ -611,22 +613,43 @@ eexp_interrupt(int reg_ptr)
ack_cmd = status & 0xf000;
if ((status & 0x0700) != 0x0200 && dev->start) {
- if (net_debug)
+ short saved_write_ptr = inw(ioaddr + WRITE_PTR);
+ if (net_debug > 1)
printk("%s: Command unit stopped, status %04x, restarting.\n",
dev->name, status);
- /* If this ever occurs we should really re-write the idle loop, reset
- the Tx list, and do a complete restart of the command unit.
- For now we rely on the Tx timeout if the resume doesn't work. */
- ack_cmd |= CUC_RESUME;
+ /* If this ever occurs we must re-write the idle loop, reset
+ the Tx list, and do a complete restart of the command unit. */
+ outw(IDLELOOP, ioaddr + WRITE_PTR);
+ outw(0, ioaddr);
+ outw(CmdNOp, ioaddr);
+ outw(IDLELOOP, ioaddr);
+ outw(IDLELOOP, SCB_CBL);
+ lp->tx_cmd_link = IDLELOOP + 4;
+ lp->tx_head = lp->tx_reap = TX_BUF_START;
+ /* Restore the saved write pointer. */
+ outw(saved_write_ptr, ioaddr + WRITE_PTR);
+ ack_cmd |= CUC_START;
}
if ((status & 0x0070) != 0x0040 && dev->start) {
short saved_write_ptr = inw(ioaddr + WRITE_PTR);
/* The Rx unit is not ready, it must be hung. Restart the receiver by
initializing the rx buffers, and issuing an Rx start command. */
- if (net_debug)
- printk("%s: Rx unit stopped, status %04x, restarting.\n",
- dev->name, status);
+ lp->stats.rx_errors++;
+ if (net_debug > 1) {
+ int cur_rxbuf = RX_BUF_START;
+ printk("%s: Rx unit stopped status %04x rx head %04x tail %04x.\n",
+ dev->name, status, lp->rx_head, lp->rx_tail);
+ while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE) {
+ int i;
+ printk(" Rx buf at %04x:", cur_rxbuf);
+ outw(cur_rxbuf, ioaddr + READ_PTR);
+ for (i = 0; i < 0x20; i += 2)
+ printk(" %04x", inw(ioaddr));
+ printk(".\n");
+ cur_rxbuf += RX_BUF_SIZE;
+ }
+ }
init_rx_bufs(dev);
outw(RX_BUF_START, SCB_RFA);
outw(saved_write_ptr, ioaddr + WRITE_PTR);
@@ -813,8 +836,7 @@ init_82586_mem(struct device *dev)
}
/* Initialize the Rx-block list. */
-static void
-init_rx_bufs(struct device *dev)
+static void init_rx_bufs(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
short ioaddr = dev->base_addr;
@@ -828,14 +850,14 @@ init_rx_bufs(struct device *dev)
outw(0x0000, ioaddr); /* Command */
outw(cur_rxbuf + RX_BUF_SIZE, ioaddr); /* Link */
outw(cur_rxbuf + 22, ioaddr); /* Buffer offset */
- outw(0x0000, ioaddr); /* Pad for dest addr. */
- outw(0x0000, ioaddr);
- outw(0x0000, ioaddr);
- outw(0x0000, ioaddr); /* Pad for source addr. */
- outw(0x0000, ioaddr);
- outw(0x0000, ioaddr);
- outw(0x0000, ioaddr); /* Pad for protocol. */
-
+ outw(0xFeed, ioaddr); /* Pad for dest addr. */
+ outw(0xF00d, ioaddr);
+ outw(0xF001, ioaddr);
+ outw(0x0505, ioaddr); /* Pad for source addr. */
+ outw(0x2424, ioaddr);
+ outw(0x6565, ioaddr);
+ outw(0xdeaf, ioaddr); /* Pad for protocol. */
+
outw(0x0000, ioaddr); /* Buffer: Actual count */
outw(-1, ioaddr); /* Buffer: Next (none). */
outw(cur_rxbuf + 0x20, ioaddr); /* Buffer: Address low */
@@ -890,7 +912,7 @@ hardware_send_packet(struct device *dev, void *buf, short length)
/* Set the next free tx region. */
lp->tx_head = tx_block + TX_BUF_SIZE;
- if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
+ if (lp->tx_head > TX_BUF_END - TX_BUF_SIZE)
lp->tx_head = TX_BUF_START;
if (net_debug > 4) {
@@ -960,7 +982,7 @@ eexp_rx(struct device *dev)
outw(data_buffer_addr + 10, ioaddr + READ_PTR);
- insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
+ insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
@@ -985,7 +1007,7 @@ eexp_rx(struct device *dev)
printk("%s: Rx next frame at %#x is %#x instead of %#x.\n", dev->name,
rx_head, next_rx_frame, rx_head + RX_BUF_SIZE);
next_rx_frame = rx_head + RX_BUF_SIZE;
- if (next_rx_frame >= RX_BUF_END - RX_BUF_SIZE)
+ if (next_rx_frame >= RX_BUF_END - RX_BUF_SIZE)
next_rx_frame = RX_BUF_START;
}
#endif
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index eda01d1..68e4823 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -13,7 +13,7 @@
*/
static char *version =
- "hp.c:v0.99.14a 12/2/93 Donald Becker (becker@super.org)\n";
+ "hp.c:v0.99.15c 2/11/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
@@ -56,7 +56,7 @@ static void hp_block_output(struct device *dev, int count,
static void hp_init_card(struct device *dev);
/* The map from IRQ number to HP_CONFIGURE register setting. */
-/* My default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */
+/* My default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */
static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
@@ -86,22 +86,17 @@ int hp_probe(struct device *dev)
int hpprobe1(struct device *dev, int ioaddr)
{
- int status, i, board_id, wordmode;
+ int i, board_id, wordmode;
char *name;
unsigned char *station_addr = dev->dev_addr;
/* Check for the HP physical address, 08 00 09 xx xx xx. */
+ /* This really isn't good enough: we may pick up HP LANCE boards
+ also! Avoid the lance 0x5757 signature. */
if (inb(ioaddr) != 0x08
|| inb(ioaddr+1) != 0x00
- || inb(ioaddr+2) != 0x09)
- return ENODEV;
-
- /* This really isn't good enough, we may pick up HP LANCE boards also! */
- /* Verify that there is a 8390 at the expected location. */
- outb(E8390_NODMA + E8390_STOP, ioaddr);
- SLOW_DOWN_IO;
- status = inb(ioaddr);
- if (status != 0x21 && status != 0x23)
+ || inb(ioaddr+2) != 0x09
+ || inb(ioaddr+14) == 0x57)
return ENODEV;
/* Set up the parameters based on the board ID.
@@ -320,9 +315,10 @@ hp_init_card(struct device *dev)
/*
* Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
+ * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * tab-width: 4
+ * c-indent-level: 4
* End:
*/
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 1d610e8..4eac67b 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -205,7 +205,7 @@ struct lance_private {
int pad0, pad1; /* Used for alignment */
};
-static unsigned long lance_probe1(short ioaddr, unsigned long mem_start);
+unsigned long lance_probe1(short ioaddr, unsigned long mem_start);
static int lance_open(struct device *dev);
static void lance_init_ring(struct device *dev);
static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
@@ -236,7 +236,7 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
return mem_start;
}
-static unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
+unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
{
struct device *dev;
struct lance_private *lp;
@@ -512,7 +512,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
}
/* Fill in the ethernet header. */
- if (!skb->arp && dev->rebuild_header(skb->data, dev)) {
+ if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
skb->dev = dev;
arp_queue (skb);
return 0;
@@ -553,11 +553,11 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
/* If any part of this buffer is >16M we must copy it to a low-memory
buffer. */
- if ((int)(skb->data) + skb->len > 0x01000000) {
+ if ((int)(skb+1) + skb->len > 0x01000000) {
if (lance_debug > 5)
printk("%s: bouncing a high-memory packet (%#x).\n",
- dev->name, (int)skb->data);
- memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
+ dev->name, (int)(skb+1));
+ memcpy(&lp->tx_bounce_buffs[entry], skb+1, skb->len);
lp->tx_ring[entry].base =
(int)(lp->tx_bounce_buffs + entry) | 0x83000000;
if (skb->free)
@@ -567,7 +567,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
/* Gimme!!! */
if(skb->free==0)
skb_kept_by_device(skb);
- lp->tx_ring[entry].base = (int)skb->data | 0x83000000;
+ lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000;
}
lp->cur_tx++;
@@ -638,11 +638,12 @@ lance_interrupt(int reg_ptr)
if (err_status & 0x0800) lp->stats.tx_carrier_errors++;
if (err_status & 0x1000) lp->stats.tx_window_errors++;
if (err_status & 0x4000) lp->stats.tx_fifo_errors++;
- /* We should re-init() after the FIFO error. */
- } else if (status & 0x18000000)
- lp->stats.collisions++;
- else
+ /* Perhaps we should re-init() after the FIFO error. */
+ } else {
+ if (status & 0x18000000)
+ lp->stats.collisions++;
lp->stats.tx_packets++;
+ }
/* We don't free the skb if it's a data-only copy in the bounce
buffer. The address checks here are sorted -- the first test
@@ -726,7 +727,7 @@ lance_rx(struct device *dev)
skb->mem_addr = skb;
skb->len = pkt_len;
skb->dev = dev;
- memcpy(skb->data,
+ memcpy((unsigned char *) (skb + 1),
(unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff),
pkt_len);
#ifdef HAVE_NETIF_RX
@@ -836,6 +837,12 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
outw(0x0142, ioaddr+LANCE_DATA); /* Resume normal operation. */
}
#endif
+
+#ifdef HAVE_DEVLIST
+static unsigned int lance_portlist[] = {0x300, 0x320, 0x340, 0x360, 0};
+struct netdev_entry lance_drv =
+{"lance", lance_probe1, LANCE_TOTAL_SIZE, lance_portlist};
+#endif
/*
* Local variables:
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index e198d55..a69754a 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -17,7 +17,7 @@
/* Routines for the NatSemi-based designs (NE[12]000). */
static char *version =
- "ne.c:v0.99-14a 12/3/93 Donald Becker (becker@super.org)\n";
+ "ne.c:v0.99-15b 2/8/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
@@ -155,11 +155,11 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
}
if (wordlength == 2) {
- /* We must set the 8390 for word mode, AND RESET IT. */
+ /* We must set the 8390 for word mode. */
int tmp;
outb_p(0x49, ioaddr + EN0_DCFG);
- tmp = inb_p(NE_BASE + NE_RESET);
- outb(tmp, NE_BASE + NE_RESET);
+ /* We used to reset the ethercard here, but it doesn't seem
+ to be necessary. */
/* Un-double the SA_prom values. */
for (i = 0; i < 16; i++)
SA_prom[i] = SA_prom[i+i];
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index dc6cf50..18c506b 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -523,7 +523,6 @@ sl_xmit(struct sk_buff *skb, struct device *dev)
{
struct tty_struct *tty;
struct slip *sl;
-
int size;
/* Find the correct SLIP channel to use. */
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 5816b83..07dc5ce 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -14,7 +14,7 @@
*/
static char *version =
- "smc-ultra.c:v0.05 12/21/93 Donald Becker (becker@super.org)\n";
+ "smc-ultra.c:v0.06 2/9/94 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
@@ -139,7 +139,7 @@ int ultraprobe1(int ioaddr, struct device *dev)
dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
{
- int addr_tbl[4] = {0x0C0000, 0x0D0000, 0xFC0000, 0xFD0000};
+ int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000};
short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 23d9abe..7663b41 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -13,6 +13,7 @@
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
+#include <linux/shm.h>
#include <asm/segment.h>
@@ -21,6 +22,8 @@ asmlinkage int sys_close(unsigned fd);
asmlinkage int sys_open(const char *, int, int);
asmlinkage int sys_brk(unsigned long);
+#define DLINFO_ITEMS 8
+
#include <linux/elf.h>
/* We need to explicitly zero any fractional pages
@@ -43,17 +46,220 @@ static void padzero(int elf_bss){
};
}
+unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, int ibcs)
+{
+ unsigned long *argv,*envp, *dlinfo;
+ unsigned long * sp;
+ struct vm_area_struct *mpnt;
+
+ mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
+ if (mpnt) {
+ mpnt->vm_task = current;
+ mpnt->vm_start = PAGE_MASK & (unsigned long) p;
+ mpnt->vm_end = TASK_SIZE;
+ mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
+ mpnt->vm_share = NULL;
+ mpnt->vm_inode = NULL;
+ mpnt->vm_offset = 0;
+ mpnt->vm_ops = NULL;
+ insert_vm_struct(current, mpnt);
+ current->stk_vma = mpnt;
+ }
+ sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
+ if(exec) sp -= DLINFO_ITEMS*2;
+ dlinfo = sp;
+ sp -= envc+1;
+ envp = sp;
+ sp -= argc+1;
+ argv = sp;
+ if (!ibcs) {
+ put_fs_long((unsigned long)envp,--sp);
+ put_fs_long((unsigned long)argv,--sp);
+ }
+
+ /* The constant numbers (0-9) that we are writing here are
+ described in the header file sys/auxv.h on at least
+ some versions of SVr4 */
+ if(exec) { /* Put this here for an ELF program interpreter */
+ struct elf_phdr * eppnt;
+ eppnt = (struct elf_phdr *) exec->e_phoff;
+ put_fs_long(3,dlinfo++); put_fs_long(load_addr + exec->e_phoff,dlinfo++);
+ put_fs_long(4,dlinfo++); put_fs_long(sizeof(struct elf_phdr),dlinfo++);
+ put_fs_long(5,dlinfo++); put_fs_long(exec->e_phnum,dlinfo++);
+ put_fs_long(9,dlinfo++); put_fs_long((unsigned long) exec->e_entry,dlinfo++);
+ put_fs_long(7,dlinfo++); put_fs_long(SHM_RANGE_START,dlinfo++);
+ put_fs_long(8,dlinfo++); put_fs_long(0,dlinfo++);
+ put_fs_long(6,dlinfo++); put_fs_long(PAGE_SIZE,dlinfo++);
+ put_fs_long(0,dlinfo++); put_fs_long(0,dlinfo++);
+ };
+
+ put_fs_long((unsigned long)argc,--sp);
+ current->arg_start = (unsigned long) p;
+ while (argc-->0) {
+ put_fs_long((unsigned long) p,argv++);
+ while (get_fs_byte(p++)) /* nothing */ ;
+ }
+ put_fs_long(0,argv);
+ current->arg_end = current->env_start = (unsigned long) p;
+ while (envc-->0) {
+ put_fs_long((unsigned long) p,envp++);
+ while (get_fs_byte(p++)) /* nothing */ ;
+ }
+ put_fs_long(0,envp);
+ current->env_end = (unsigned long) p;
+ return sp;
+}
+
+
+/* This is much more generalized than the library routine read function,
+ so we keep this separate. Techincally the library read function
+ is only provided so that we can read a.out libraries that have
+ an ELF header */
+
+static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
+ struct inode * interpreter_inode)
+{
+ struct file * file;
+ struct elf_phdr *elf_phdata = NULL;
+ struct elf_phdr *eppnt;
+ unsigned int len;
+ unsigned int load_addr;
+ int elf_exec_fileno;
+ int elf_bss;
+ int old_fs, retval;
+ unsigned int last_bss;
+ int error;
+ int i, k;
+
+ elf_bss = 0;
+ last_bss = 0;
+ error = load_addr = 0;
+
+ /* First of all, some simple consistency checks */
+ if((interp_elf_ex->e_type != ET_EXEC &&
+ interp_elf_ex->e_type != ET_DYN) ||
+ (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
+ (!interpreter_inode->i_op || !interpreter_inode->i_op->bmap ||
+ !interpreter_inode->i_op->default_file_ops->mmap)){
+ return 0xffffffff;
+ };
+
+ /* Now read in all of the header information */
+
+ if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE)
+ return 0xffffffff;
+
+ elf_phdata = (struct elf_phdr *)
+ kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
+ if(!elf_phdata) return 0xffffffff;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+ retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
+ sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+ set_fs(old_fs);
+
+ elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
+ if (elf_exec_fileno < 0) return 0xffffffff;
+ file = current->filp[elf_exec_fileno];
+
+ eppnt = elf_phdata;
+ for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+ if(eppnt->p_type == PT_LOAD) {
+ error = do_mmap(file,
+ eppnt->p_vaddr & 0xfffff000,
+ eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
+ eppnt->p_offset & 0xfffff000);
+
+ if(!load_addr && interp_elf_ex->e_type == ET_DYN)
+ load_addr = error;
+ k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
+ if(k > elf_bss) elf_bss = k;
+ if(error < 0 && error > -1024) break; /* Real error */
+ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
+ if(k > last_bss) last_bss = k;
+ }
+
+ /* Now use mmap to map the library into memory. */
+
+
+ sys_close(elf_exec_fileno);
+ if(error < 0 && error > -1024) {
+ kfree(elf_phdata);
+ return 0xffffffff;
+ }
+
+ padzero(elf_bss);
+ len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
+
+ /* Map the last of the bss segment */
+ if (last_bss > len)
+ do_mmap(NULL, len, last_bss-len,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, 0);
+ kfree(elf_phdata);
+
+ return ((unsigned int) interp_elf_ex->e_entry) + load_addr;
+}
+
+static unsigned int load_aout_interp(struct exec * interp_ex,
+ struct inode * interpreter_inode)
+{
+ int retval;
+ unsigned int elf_entry;
+
+ current->brk = interp_ex->a_bss +
+ (current->end_data = interp_ex->a_data +
+ (current->end_code = interp_ex->a_text));
+ elf_entry = interp_ex->a_entry;
+
+
+ if (N_MAGIC(*interp_ex) == OMAGIC) {
+ do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, 0);
+ retval = read_exec(interpreter_inode, 32, (char *) 0,
+ interp_ex->a_text+interp_ex->a_data);
+ } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
+ do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, 0);
+ retval = read_exec(interpreter_inode,
+ N_TXTOFF(*interp_ex) ,
+ (char *) N_TXTADDR(*interp_ex),
+ interp_ex->a_text+interp_ex->a_data);
+ } else
+ retval = -1;
+
+ if(retval >= 0)
+ do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) &
+ 0xfffff000, interp_ex->a_bss,
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_FIXED|MAP_PRIVATE, 0);
+ if(retval < 0) return 0xffffffff;
+ return elf_entry;
+}
+
/*
* These are the functions used to load ELF style executables and shared
* libraries. There is no binary dependent code anywhere else.
*/
+#define INTERPRETER_NONE 0
+#define INTERPRETER_AOUT 1
+#define INTERPRETER_ELF 2
+
int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct elfhdr elf_ex;
+ struct elfhdr interp_elf_ex;
struct file * file;
- struct exec ex;
+ struct exec interp_ex;
struct inode *interpreter_inode;
+ unsigned int load_addr;
+ unsigned int interpreter_type = INTERPRETER_NONE;
int i;
int old_fs;
int error;
@@ -69,6 +275,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
char passed_fileno[6];
status = 0;
+ load_addr = 0;
elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
if (elf_ex.e_ident[0] != 0x7f ||
@@ -141,11 +348,14 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
retval = read_exec(interpreter_inode,0,bprm->buf,128);
if(retval >= 0){
- ex = *((struct exec *) bprm->buf); /* exec-header */
+ interp_ex = *((struct exec *) bprm->buf); /* exec-header */
+ interp_elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
-#if 0
- printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
-#endif
+ };
+ if(retval < 0) {
+ kfree (elf_phdata);
+ kfree(elf_interpreter);
+ return retval;
};
};
elf_ppnt++;
@@ -155,16 +365,28 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* Some simple consistency checks for the interpreter */
if(elf_interpreter){
+ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
if(retval < 0) {
kfree(elf_interpreter);
kfree(elf_phdata);
return -ELIBACC;
};
- if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
- kfree(elf_interpreter);
- kfree(elf_phdata);
- return -ELIBBAD;
- };
+ /* Now figure out which format our binary is */
+ if((N_MAGIC(interp_ex) != OMAGIC) &&
+ (N_MAGIC(interp_ex) != ZMAGIC) &&
+ (N_MAGIC(interp_ex) != QMAGIC))
+ interpreter_type = INTERPRETER_ELF;
+
+ if (interp_elf_ex.e_ident[0] != 0x7f ||
+ strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0)
+ interpreter_type &= ~INTERPRETER_ELF;
+
+ if(!interpreter_type)
+ {
+ kfree(elf_interpreter);
+ kfree(elf_phdata);
+ return -ELIBBAD;
+ };
}
/* OK, we are done with that, now set up the arg stuff,
@@ -173,12 +395,14 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->sh_bang) {
char * passed_p;
- sprintf(passed_fileno, "%d", elf_exec_fileno);
- passed_p = passed_fileno;
+ if(interpreter_type == INTERPRETER_AOUT) {
+ sprintf(passed_fileno, "%d", elf_exec_fileno);
+ passed_p = passed_fileno;
- if(elf_interpreter) {
- bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
- bprm->argc++;
+ if(elf_interpreter) {
+ bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
+ bprm->argc++;
+ };
};
if (!bprm->p) {
if(elf_interpreter) {
@@ -217,49 +441,27 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if(elf_ppnt->p_type == PT_INTERP) {
/* Set these up so that we are able to load the interpreter */
- current->brk = ex.a_bss +
- (current->end_data = ex.a_data +
- (current->end_code = ex.a_text));
- elf_entry = ex.a_entry;
-
- /* Now load the interpreter into user address space */
- set_fs(old_fs);
-
- if (N_MAGIC(ex) == OMAGIC) {
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
- retval = read_exec(interpreter_inode, 32, (char *) 0,
- ex.a_text+ex.a_data);
- iput(interpreter_inode);
- } else if (N_MAGIC(ex) == ZMAGIC || N_MAGIC(ex) == QMAGIC) {
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
- retval = read_exec(interpreter_inode,
- N_TXTOFF(ex) ,
- (char *) N_TXTADDR(ex),
- ex.a_text+ex.a_data);
- iput(interpreter_inode);
- } else
- retval = -1;
-
- old_fs = get_fs();
- set_fs(get_ds());
-
- if(retval >= 0)
- do_mmap(NULL, (ex.a_text + ex.a_data + 0xfff) &
- 0xfffff000, ex.a_bss,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
+ /* Now load the interpreter into user address space */
+ set_fs(old_fs);
- kfree(elf_interpreter);
+ if(interpreter_type & 1) elf_entry =
+ load_aout_interp(&interp_ex, interpreter_inode);
+
+ if(interpreter_type & 2) elf_entry =
+ load_elf_interp(&interp_elf_ex, interpreter_inode);
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ iput(interpreter_inode);
+ kfree(elf_interpreter);
- if(retval < 0) {
- kfree(elf_phdata);
- send_sig(SIGSEGV, current, 0);
- return 0;
- };
+ if(elf_entry == 0xffffffff) {
+ printk("Unable to load interpreter\n");
+ kfree(elf_phdata);
+ send_sig(SIGSEGV, current, 0);
+ return 0;
+ };
};
@@ -276,6 +478,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
#endif
+ if(!load_addr)
+ load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
k = elf_ppnt->p_vaddr;
if(k > start_code) start_code = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
@@ -285,14 +489,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if(end_data < k) end_data = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
if(k > elf_brk) elf_brk = k;
-
- if(status == 0xffffffff) {
- set_fs(old_fs);
- kfree(elf_phdata);
- send_sig(SIGSEGV, current, 0);
- return 0;
- };
- };
+ };
elf_ppnt++;
};
set_fs(old_fs);
@@ -307,8 +504,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->start_stack = p = elf_stack - 4;
#endif
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
- bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc,0);
- if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
+ bprm->p = (unsigned long)
+ create_elf_tables((char *)bprm->p,
+ bprm->argc,
+ bprm->envc,
+ (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
+ load_addr,
+ (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
+ if(interpreter_type == INTERPRETER_AOUT)
+ current->arg_start += strlen(passed_fileno) + 1;
current->start_brk = current->brk = elf_brk;
current->end_code = end_code;
current->start_code = start_code;
@@ -324,6 +528,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
padzero(elf_bss);
+ /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
+ and some applications "depend" upon this behavior.
+ Since we do not have the power to recompile these, we
+ emulate the SVr4 behavior. Sigh. */
+ error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE, 0);
+
regs->eip = elf_entry; /* eip, magic happens :-) */
regs->esp = bprm->p; /* stack pointer */
if (current->flags & PF_PTRACED)
@@ -331,8 +542,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return 0;
}
-/* This is really simpleminded and specialized - we are loading an a.out library that is given
- an ELF header */
+/* This is really simpleminded and specialized - we are loading an
+ a.out library that is given an ELF header. */
int load_elf_library(int fd){
struct file * file;
diff --git a/fs/buffer.c b/fs/buffer.c
index 17fc97c..1f63919 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -954,7 +954,9 @@ int shrink_buffers(unsigned int priority)
bh = free_list;
i = nr_buffers >> priority;
for ( ; i-- > 0 ; bh = bh->b_next_free) {
- if (bh->b_count) {
+ if (bh->b_count ||
+ (priority >= 5 &&
+ mem_map[MAP_NR((unsigned long) bh->b_data)] > 1)) {
put_last_free(bh);
continue;
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index a513b9c..fdd92da 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -45,7 +45,7 @@ static int read_core(struct inode * inode, struct file * file,char * buf, int co
if (p >= high_memory + PAGE_SIZE)
return 0;
if (count > high_memory + PAGE_SIZE - p)
- count = high_memory - p;
+ count = high_memory + PAGE_SIZE - p;
read = 0;
if (p < sizeof(struct user) && count > 0) {
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 68d5330..4b10406 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -5,9 +5,10 @@
*
* Global definitions for the Ethernet IEE 802.3 interface.
*
- * Version: @(#)if_ether.h 1.0.1 03/15/93
+ * Version: @(#)if_ether.h 1.0.1a 02/08/94
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,12 +19,14 @@
#define _LINUX_IF_ETHER_H
-/* IEEE 802.3 Ethernet magic constants. */
-#define ETH_ALEN 6 /* #bytes in eth addr */
-#define ETH_HLEN 14 /* #bytes in eth header */
-#define ETH_ZLEN 60 /* min #bytes in frame */
-#define ETH_FLEN 1536 /* max #bytes in frame */
-#define ETH_DLEN (ETH_FLEN - ETH_HLEN) /* max #bytes of data */
+/* IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
+ and FCS/CRC (frame check sequence). */
+#define ETH_ALEN 6 /* Octets in one ethernet addr */
+#define ETH_HLEN 14 /* Total octets in header. */
+#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
+#define ETH_DATA_LEN 1500 /* Max. octets in payload */
+#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
+
/* These are the defined Ethernet Protocol ID's. */
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
@@ -38,9 +41,6 @@
#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
-/* Define the Ethernet Broadcast Address (48 bits set to "1"). */
-#define ETH_A_BCAST "\377\377\377\377\377\377"
-
/* This is an Ethernet frame header. */
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
@@ -48,21 +48,6 @@ struct ethhdr {
unsigned short h_proto; /* packet type ID field */
};
-/* This is the complete Ethernet frame. */
-struct ethframe {
- struct ethhdr f_hdr; /* frame header */
- char f_data[ETH_DLEN]; /* frame data (variable)*/
-};
-
-
-/* Receiver modes */
-#define ETH_MODE_MONITOR 1 /* Monitor mode - no receive */
-#define ETH_MODE_PHYS 2 /* Physical address receive only */
-#define ETH_MODE_BCAST 3 /* Broadcast receive + mode 2 */
-#define ETH_MODE_MCAST 4 /* Multicast receive + mode 3 */
-#define ETH_MODE_PROMISC 5 /* Promiscuous mode - receive all */
-
-
/* Ethernet statistics collection data. */
struct enet_statistics{
int rx_packets; /* total packets received */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 49fdb90..793fef3 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -399,7 +399,7 @@ extern long tty_init(long);
extern void flush_input(struct tty_struct * tty);
extern void flush_output(struct tty_struct * tty);
-extern void wait_until_sent(struct tty_struct * tty);
+extern void wait_until_sent(struct tty_struct * tty, int timeout);
extern int check_change(struct tty_struct * tty, int channel);
extern void stop_tty(struct tty_struct * tty);
extern void start_tty(struct tty_struct * tty);
diff --git a/ipc/util.c b/ipc/util.c
index c7bebd7..e2e3007 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -45,24 +45,19 @@ void ipc_init (void)
* to ipc resources. return 0 if allowed
*/
int ipcperms (struct ipc_perm *ipcp, short flag)
-{
- int i; mode_t perm; uid_t euid; int egid;
-
+{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
+ int requested_mode, granted_mode;
+
if (suser())
return 0;
-
- perm = S_IRWXO; euid = current->euid;
-
- if (euid == ipcp->cuid || euid == ipcp->uid)
- perm = S_IRWXU;
- else {
- for (i = 0; (egid = current->groups[i]) != NOGROUP; i++)
- if ((egid == ipcp->cgid) || (egid == ipcp->gid)) {
- perm = S_IRWXG;
- break;
- }
- }
- if (!(flag & perm) || flag & perm & ~ipcp->mode)
+ requested_mode = (flag >> 6) | (flag >> 3) | flag;
+ granted_mode = ipcp->mode;
+ if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
+ granted_mode >>= 6;
+ else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
+ granted_mode >>= 3;
+ /* is there some bit set in requested_mode but not in granted_mode? */
+ if (requested_mode & ~granted_mode & 0007)
return -1;
return 0;
}
diff --git a/kernel/ksyms.sh b/kernel/ksyms.sh
index d46f091..1a99ed5 100644
--- a/kernel/ksyms.sh
+++ b/kernel/ksyms.sh
@@ -10,7 +10,7 @@
#
#
-trap "rm -f ksyms.tmp ksyms.lst" 1 2
+trap "rm -f ksyms.tmp ksyms.lst ; exit 1" 1 2
sed -e '/^#/d' -e '/^[ ]*$/d' ksyms.lst | sort > ksyms.tmp
diff --git a/kernel/traps.c b/kernel/traps.c
index e0145cc..7321836 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -89,8 +89,8 @@ asmlinkage void alignment_check(void);
printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
- printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
- regs->esi, regs->edi, regs->ebp, regs->esp);
+ printk("esi: %08lx edi: %08lx ebp: %08lx\n",
+ regs->esi, regs->edi, regs->ebp);
printk("ds: %04x es: %04x fs: %04x gs: %04x\n",
regs->ds, regs->es, regs->fs, regs->gs);
store_TR(i);
@@ -98,11 +98,6 @@ asmlinkage void alignment_check(void);
for(i=0;i<20;i++)
printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
printk("\n");
-#if 0
- for(i=0;i<5;i++)
- printk("%08lx ", get_seg_long(regs->ss,(i+(unsigned long *)regs->esp)));
- printk("\n");
-#endif
do_exit(SIGSEGV);
}
diff --git a/net/inet/ip.c b/net/inet/ip.c
index d95e4cd..c8954c4 100644
--- a/net/inet/ip.c
+++ b/net/inet/ip.c
@@ -34,6 +34,12 @@
* Alan Cox : Save IP header pointer for later
* Alan Cox : ip option setting
* Alan Cox : Use ip_tos/ip_ttl settings
+ * Alan Cox : Fragmentation bogosity removed
+ * (Thanks to Mark.Bush@prg.ox.ac.uk)
+ * Dmitry Gordchanin : Send of a raw packet crash fix.
+ * Alan Cox : Silly ip bug when an overlength
+ * fragment turns up. Now frees the
+ * queue.
*
* To Fix:
* IP option processing is mostly not needed. ip_forward needs to know about routing rules
@@ -785,6 +791,7 @@ static struct sk_buff *ip_glue(struct ipq *qp)
if(count+fp->len>skb->len)
{
printk("Invalid fragment list: Fragment over size.\n");
+ ip_free(qp);
kfree_skb(skb,FREE_WRITE);
return NULL;
}
@@ -970,7 +977,9 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
/* Point into the IP datagram header. */
raw = skb->data;
iph = (struct iphdr *) (raw + dev->hard_header_len);
-
+
+ skb->ip_hdr = iph;
+
/* Setup starting values. */
hlen = (iph->ihl * sizeof(unsigned long));
left = ntohs(iph->tot_len) - hlen;
@@ -1008,6 +1017,7 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
while(left > 0)
{
len = left;
+#ifdef OLD
if (len+8 > mtu)
len = (dev->mtu - hlen - 8);
if ((left - len) >= 8)
@@ -1015,6 +1025,18 @@ static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct
len /= 8;
len *= 8;
}
+#else
+ /* IF: it doesn't fit, use 'mtu' - the data space left */
+ if (len > mtu)
+ len = mtu;
+ /* IF: we are not sending upto and including the packet end
+ then align the next start on an eight byte boundary */
+ if (len < left)
+ {
+ len/=8;
+ len*=8;
+ }
+#endif
DPRINTF((DBG_IP,"IP: frag: creating fragment of %d bytes (%d total)\n",
len, len + hlen));
@@ -1368,6 +1390,7 @@ ip_queue_xmit(struct sock *sk, struct device *dev,
ptr = skb->data;
ptr += dev->hard_header_len;
iph = (struct iphdr *)ptr;
+ skb->ip_hdr = iph;
iph->tot_len = ntohs(skb->len-dev->hard_header_len);
if(skb->len > dev->mtu)
diff --git a/net/inet/skbuff.h b/net/inet/skbuff.h
index e976385..d3bcc09 100644
--- a/net/inet/skbuff.h
+++ b/net/inet/skbuff.h
@@ -72,8 +72,7 @@ struct sk_buff {
volatile char acked,
used,
free,
- arp,
- urg_used;
+ arp;
unsigned char tries,lock; /* Lock is now unused */
unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
unsigned long padding[0];
diff --git a/net/inet/sock.c b/net/inet/sock.c
index c937071..45383b3 100644
--- a/net/inet/sock.c
+++ b/net/inet/sock.c
@@ -130,7 +130,7 @@ print_sk(struct sock *sk)
printk(" retransmits = %ld, timeout = %d\n", sk->retransmits, sk->timeout);
printk(" cong_window = %d, packets_out = %d\n", sk->cong_window,
sk->packets_out);
- printk(" urg = %d shutdown=%d\n", sk->urg, sk->shutdown);
+ printk(" shutdown=%d\n", sk->shutdown);
}
@@ -842,6 +842,8 @@ inet_create(struct socket *sock, int protocol)
sk->acked_seq = 0;
sk->copied_seq = 0;
sk->fin_seq = 0;
+ sk->urg_seq = 0;
+ sk->urg_data = 0;
sk->proc = 0;
sk->rtt = TCP_WRITE_TIME << 3;
sk->rto = TCP_WRITE_TIME;
@@ -859,7 +861,6 @@ inet_create(struct socket *sock, int protocol)
sk->priority = 1;
sk->shutdown = 0;
- sk->urg = 0;
sk->keepopen = 0;
sk->zapped = 0;
sk->done = 0;
diff --git a/net/inet/sock.h b/net/inet/sock.h
index 3fb08a9..d6dbb6a 100644
--- a/net/inet/sock.h
+++ b/net/inet/sock.h
@@ -61,6 +61,8 @@ struct sock {
unsigned long rcv_ack_seq;
unsigned long window_seq;
unsigned long fin_seq;
+ unsigned long urg_seq;
+ unsigned long urg_data;
/*
* Not all are volatile, but some are, so we
@@ -112,7 +114,6 @@ struct sock {
volatile unsigned short cong_count;
volatile unsigned short ssthresh;
volatile unsigned short packets_out;
- volatile unsigned short urg;
volatile unsigned short shutdown;
volatile unsigned long rtt;
volatile unsigned long mdev;
diff --git a/net/inet/tcp.c b/net/inet/tcp.c
index 221111d..b57e1ed 100644
--- a/net/inet/tcp.c
+++ b/net/inet/tcp.c
@@ -340,10 +340,8 @@ tcp_readable(struct sock *sk)
if (before(counted, skb->h.th->seq)) /* Found a hole so stops here */
break;
sum = skb->len -(counted - skb->h.th->seq); /* Length - header but start from where we are up to (avoid overlaps) */
- if (skb->h.th->syn) sum++;
- if (skb->h.th->urg) {
- sum -= ntohs(skb->h.th->urg_ptr); /* Dont count urg data */
- }
+ if (skb->h.th->syn)
+ sum++;
if (sum >= 0) { /* Add it up, move on */
amount += sum;
if (skb->h.th->syn) amount--;
@@ -352,6 +350,9 @@ tcp_readable(struct sock *sk)
if (amount && skb->h.th->psh) break;
skb =(struct sk_buff *)skb->next; /* Move along */
} while(skb != sk->rqueue);
+ if (sk->urg_data &&
+ (sk->urg_seq - sk->copied_seq) < (counted - sk->copied_seq))
+ amount--; /* don't count urg data */
restore_flags(flags);
DPRINTF((DBG_TCP, "tcp readable returning %d bytes\n", amount));
if(sk->debug)
@@ -485,20 +486,14 @@ tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
}
case SIOCATMARK:
{
- struct sk_buff *skb;
int answ = 0;
/*
* Try to figure out if we need to read
* some urgent data.
*/
- sk->inuse = 1;
- if ((skb=skb_peek(&sk->rqueue)) != NULL)
- {
- if (sk->copied_seq+1 == skb->h.th->seq && skb->h.th->urg)
- answ = 1;
- }
- release_sock(sk);
+ if (sk->urg_data && sk->copied_seq+1 == sk->urg_seq)
+ answ = 1;
err=verify_area(VERIFY_WRITE,(void *) arg,
sizeof(unsigned long));
if(err)
@@ -1252,98 +1247,51 @@ static int
tcp_read_urg(struct sock * sk, int nonblock,
unsigned char *to, int len, unsigned flags)
{
- int copied = 0;
- struct sk_buff *skb;
+ struct wait_queue wait = { current, NULL };
- DPRINTF((DBG_TCP, "tcp_read_urg(sk=%X, to=%X, len=%d, flags=%X)\n",
- sk, to, len, flags));
+ while (len > 0) {
+ if (sk->urg_data && sk->urg_data != URG_READ) {
+ char c = sk->urg_data;
+ if (!(flags & MSG_PEEK))
+ sk->urg_data = URG_READ;
+ put_fs_byte(c, to);
+ return 1;
+ }
- while(len > 0)
- {
- sk->inuse = 1;
- while(sk->urg==0 || skb_peek(&sk->rqueue) == NULL) {
if (sk->err) {
- int tmp;
-
- release_sock(sk);
- if (copied) return(copied);
- tmp = -sk->err;
+ int tmp = -sk->err;
sk->err = 0;
- return(tmp);
+ return tmp;
}
if (sk->state == TCP_CLOSE || sk->done) {
- release_sock(sk);
- if (copied) return(copied);
if (!sk->done) {
sk->done = 1;
- return(0);
+ return 0;
}
- return(-ENOTCONN);
- }
-
- if (sk->shutdown & RCV_SHUTDOWN) {
- release_sock(sk);
- if (copied == 0)
- sk->done = 1;
- return(copied);
+ return -ENOTCONN;
}
- if (nonblock || copied) {
- release_sock(sk);
- if (copied) return(copied);
- return(-EAGAIN);
+ if (sk->shutdown & RCV_SHUTDOWN) {
+ sk->done = 1;
+ return 0;
}
- /* Now at this point, we may have gotten some data. */
- release_sock(sk);
- cli();
- if ((sk->urg == 0 || skb_peek(&sk->rqueue) == NULL) &&
- sk->err == 0 && !(sk->shutdown & RCV_SHUTDOWN)) {
- interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked) {
- sti();
- if (copied) return(copied);
- return(-ERESTARTSYS);
- }
- }
- sk->inuse = 1;
- sti();
- }
+ if (nonblock)
+ return -EAGAIN;
- skb = skb_peek(&sk->rqueue);
- do {
- int amt;
-
- if (before(sk->copied_seq+1, skb->h.th->seq))
- break;
- if (skb->h.th->urg && !skb->urg_used) {
- if (skb->h.th->urg_ptr == 0) {
- skb->h.th->urg_ptr = ntohs(skb->len);
- }
- amt = min(ntohs(skb->h.th->urg_ptr),len);
- if(amt)
- {
- memcpy_tofs(to,(unsigned char *)(skb->h.th) +
- skb->h.th->doff*4, amt);
- }
+ if (current->signal & ~current->blocked)
+ return -ERESTARTSYS;
- if (!(flags & MSG_PEEK)) {
- skb->urg_used = 1;
- sk->urg--;
- }
- cleanup_rbuf(sk);
- release_sock(sk);
- copied += amt;
- return(copied);
- }
- skb =(struct sk_buff *)skb->next;
- } while(skb != sk->rqueue);
- }
-/*sk->urg = 0;*/
- cleanup_rbuf(sk);
- release_sock(sk);
- return(0);
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(sk->sleep, &wait);
+ if ((!sk->urg_data || sk->urg_data == URG_READ) &&
+ sk->err == 0 && !(sk->shutdown & RCV_SHUTDOWN))
+ schedule();
+ remove_wait_queue(sk->sleep, &wait);
+ current->state = TASK_RUNNING;
+ }
+ return 0;
}
@@ -1352,31 +1300,31 @@ static int
tcp_read(struct sock *sk, unsigned char *to,
int len, int nonblock, unsigned flags)
{
- int copied=0; /* will be used to say how much has been copied. */
+ int copied = 0; /* will be used to say how much has been copied. */
struct sk_buff *skb;
unsigned long offset;
- unsigned long used;
int err;
- if (len == 0) return(0);
- if (len < 0) {
- return(-EINVAL);
- }
+ if (len == 0)
+ return 0;
+
+ if (len < 0)
+ return -EINVAL;
err=verify_area(VERIFY_WRITE,to,len);
if(err)
return err;
/* This error should be checked. */
- if (sk->state == TCP_LISTEN) return(-ENOTCONN);
+ if (sk->state == TCP_LISTEN)
+ return -ENOTCONN;
/* Urgent data needs to be handled specially. */
- if ((flags & MSG_OOB))
- return(tcp_read_urg(sk, nonblock, to, len, flags));
+ if (flags & MSG_OOB)
+ return tcp_read_urg(sk, nonblock, to, len, flags);
/* So no-one else will use this socket. */
sk->inuse = 1;
-
skb=skb_peek(&sk->rqueue);
DPRINTF((DBG_TCP, "tcp_read(sk=%X, to=%X, len=%d, nonblock=%d, flags=%X)\n",
@@ -1386,8 +1334,7 @@ tcp_read(struct sock *sk, unsigned char *to,
/* skb->used just checks to see if we've gone all the way around. */
/* While no data, or first data indicates some is missing, or data is used */
- while(skb == NULL ||
- before(sk->copied_seq+1, skb->h.th->seq) || skb->used) {
+ while(skb == NULL || skb->used || before(sk->copied_seq+1, skb->h.th->seq)) {
DPRINTF((DBG_TCP, "skb = %X:\n", skb));
cleanup_rbuf(sk);
if (sk->err)
@@ -1465,8 +1412,8 @@ tcp_read(struct sock *sk, unsigned char *to,
continue;
}
- if (skb_peek(&sk->rqueue) == NULL ||
- before(sk->copied_seq+1, sk->rqueue->h.th->seq)) {
+ skb = skb_peek(&sk->rqueue);
+ if (skb == NULL || before(sk->copied_seq+1, skb->h.th->seq)) {
if(sk->debug)
printk("Read wait sleep\n");
interruptible_sleep_on(sk->sleep);
@@ -1492,42 +1439,42 @@ tcp_read(struct sock *sk, unsigned char *to,
}
/*
+ * are we at urgent data?
+ */
+ if (sk->urg_data && sk->copied_seq+1 == sk->urg_seq) {
+ if (sk->urg_data == URG_READ) {
+ if (copied || (flags & MSG_PEEK)) {
+ release_sock(sk);
+ return copied;
+ }
+ sk->urg_data = 0;
+ sk->copied_seq++;
+ } else {
+ release_sock(sk);
+ if (copied)
+ return copied;
+ send_sig(SIGURG, current, 0);
+ return -EINTR;
+ }
+ }
+
+ /*
* Copy anything from the current block that needs
* to go into the user buffer.
*/
offset = sk->copied_seq+1 - skb->h.th->seq;
if (skb->h.th->syn) offset--;
+
if (offset < skb->len) /* Some of the packet is useful */
{
- /*
- * If there is urgent data we must either
- * return or skip over it.
- */
- if (skb->h.th->urg)
- {
- if (skb->urg_used)
- {
- sk->copied_seq += ntohs(skb->h.th->urg_ptr);
- offset += ntohs(skb->h.th->urg_ptr);
- if (offset >= skb->len)
- {
- skb->used = 1;
- skb =(struct sk_buff *)skb->next;
- continue;
- }
- }
- else
- {
- release_sock(sk);
- if (copied)
- return(copied);
- send_sig(SIGURG, current, 0);
- return(-EINTR);
- }
- }
/* Ok so how much can we use ? */
- used = min(skb->len - offset, len);
+ unsigned long used = skb->len - offset;
+ if (len < used)
+ used = len;
+ /* do we have urgent data here? */
+ if (sk->urg_data && sk->urg_seq - (sk->copied_seq+1) < used)
+ used = sk->urg_seq - (sk->copied_seq+1);
/* Copy it */
memcpy_tofs(to,((unsigned char *)skb->h.th) +
skb->h.th->doff*4 + offset, used);
@@ -1540,23 +1487,11 @@ tcp_read(struct sock *sk, unsigned char *to,
sk->copied_seq += used;
/*
- * Mark this data used if we are really reading it,
- * and if it doesn't contain any urgent data. And we
+ * Mark this data used if we are really reading it, and we
* have used all the data.
*/
- if (!(flags & MSG_PEEK) &&
- (!skb->h.th->urg || skb->urg_used) &&
- (used + offset >= skb->len))
+ if (!(flags & MSG_PEEK) && (used + offset >= skb->len))
skb->used = 1;
-
- /*
- * See if this is the end of a message or if the
- * remaining data is urgent.
- */
- if (/*skb->h.th->psh || */skb->h.th->urg)
- {
- break;
- }
}
else
{ /* already used this data, must be a retransmit */
@@ -1933,7 +1868,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb,
newsk->send_seq = jiffies * SEQ_TICK - seq_offset;
newsk->window_seq = newsk->send_seq;
newsk->rcv_ack_seq = newsk->send_seq;
- newsk->urg =0;
+ newsk->urg_data = 0;
newsk->retransmits = 0;
newsk->destroy = 0;
newsk->timer.data = (unsigned long)newsk;
@@ -2911,32 +2846,54 @@ tcp_data(struct sk_buff *skb, struct sock *sk,
static int
-tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long saddr)
+tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long saddr, unsigned long len)
{
- extern int kill_pg(int pg, int sig, int priv);
- extern int kill_proc(int pid, int sig, int priv);
-
- if (!sk->dead)
- sk->data_ready(sk,0);
+ unsigned long ptr;
+ extern int kill_pg(int pg, int sig, int priv);
+ extern int kill_proc(int pid, int sig, int priv);
+
+ if (!sk->dead)
+ sk->data_ready(sk,0);
- if (sk->urginline) {
- th->urg = 0;
- th->psh = 1;
- return(0);
- }
+ if (sk->urginline) {
+ th->urg = 0;
+ th->psh = 1;
+ return 0;
+ }
- if (!sk->urg) {
- /* So if we get more urgent data, we don't signal the user again. */
- if (sk->proc != 0) {
- if (sk->proc > 0) {
- kill_proc(sk->proc, SIGURG, 1);
- } else {
- kill_pg(-sk->proc, SIGURG, 1);
+ ptr = ntohs(th->urg_ptr);
+ if (ptr)
+ ptr--;
+
+ /* is the urgent data in this packet at all? */
+ if (th->doff*4 + ptr >= len)
+ return 0;
+
+ /* have we already seen and read this? */
+ if (after(sk->copied_seq+1, th->seq+ptr))
+ return 0;
+
+ /* is this a duplicate? */
+ if (sk->urg_data && sk->urg_seq == th->seq+ptr)
+ return 0;
+
+ /*
+ * We signal the user only for the first urgent data: if urgent
+ * data already exists, no signal is sent
+ */
+ if (!sk->urg_data || sk->urg_data == URG_READ) {
+ if (sk->proc != 0) {
+ if (sk->proc > 0) {
+ kill_proc(sk->proc, SIGURG, 1);
+ } else {
+ kill_pg(-sk->proc, SIGURG, 1);
+ }
}
}
- }
- sk->urg++;
- return(0);
+
+ sk->urg_data = 0x100 | *(ptr + th->doff*4 + (unsigned char *) th);
+ sk->urg_seq = th->seq + ptr;
+ return 0;
}
@@ -3301,15 +3258,14 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
skb->acked = 0;
skb->used = 0;
skb->free = 0;
- skb->urg_used = 0;
skb->saddr = daddr;
skb->daddr = saddr;
th->seq = ntohl(th->seq);
- /* We may need to add it to the backlog here. */
- cli();
- if (sk->inuse) {
+ /* We may need to add it to the backlog here. */
+ cli();
+ if (sk->inuse) {
if (sk->back_log == NULL) {
sk->back_log = skb;
skb->next = skb;
@@ -3434,7 +3390,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
}
}
if (th->urg) {
- if (tcp_urg(sk, th, saddr)) {
+ if (tcp_urg(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
@@ -3622,7 +3578,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
* already in the established state.
*/
if (th->urg) {
- if (tcp_urg(sk, th, saddr)) {
+ if (tcp_urg(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
@@ -3637,7 +3593,7 @@ if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
}
if (th->urg) {
- if (tcp_urg(sk, th, saddr)) {
+ if (tcp_urg(sk, th, saddr, len)) {
kfree_skb(skb, FREE_READ);
release_sock(sk);
return(0);
diff --git a/net/inet/tcp.h b/net/inet/tcp.h
index e154d5e..5dcdaf5 100644
--- a/net/inet/tcp.h
+++ b/net/inet/tcp.h
@@ -30,6 +30,9 @@
#define MIN_WRITE_SPACE 2048
#define TCP_WINDOW_DIFF 2048
+/* marks the urg_data as read */
+#define URG_READ 0xdeadbeef
+
#define TCP_RETR1 7 /*
* This is howmany retries it does before it
* tries to figure out if the gateway is
diff --git a/zBoot/Makefile b/zBoot/Makefile
index f4fc25b..ff34719 100644
--- a/zBoot/Makefile
+++ b/zBoot/Makefile
@@ -6,7 +6,7 @@ SYSTEM = ../tools/zSystem
zOBJECTS = $(HEAD) inflate.o unzip.o misc.o
-CFLAGS = -O6 -DSTDC_HEADERS $(TEST)
+CFLAGS = -O2 -DSTDC_HEADERS $(TEST)
.c.s:
$(CC) $(CFLAGS) -S -o $*.s $<