Commit 9e11983a authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.15f

parent 350827b4
......@@ -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.
......
VERSION = 0.99
PATCHLEVEL = 15
ALPHA = e
ALPHA = f
all: Version zImage
......
......@@ -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); */
......
......@@ -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);
......
......@@ -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);
......
......@@ -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:
*/
......@@ -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:
*/
......@@ -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 };
......
......@@ -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");
}
......
......@@ -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],
......
......@@ -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
......
......@@ -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:
*/
......@@ -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:
......
......@@ -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];
......
......@@ -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. */
......
......@@ -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] ;
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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) {
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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)
......
......@@ -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];
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......@@ -1491,6 +1438,26 @@ tcp_read(struct sock *sk, unsigned char *to,
/* That may have been null if we were beaten, if so we loop again */
}
/*
* 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.
......@@ -1498,36 +1465,16 @@ tcp_read(struct sock *sk, unsigned char *to,
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);
......
......@@ -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
......
......@@ -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 $<
......
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