aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1994-01-03 10:27:45 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:24 -0400
commit8c14943430cec122e60f8065d087c095b5b54eca (patch)
tree236a6837f1ae3ed632edb61f2f46a020cc9f106c
parent5a09e4bfb5fefaf040962a64d74a4ac43b2d20e5 (diff)
downloadarchive-8c14943430cec122e60f8065d087c095b5b54eca.tar.gz
ALPHA-pl14k
-rw-r--r--Makefile6
-rw-r--r--config.in2
-rw-r--r--drivers/block/hd.c12
-rw-r--r--drivers/char/console.c4
-rw-r--r--drivers/char/serial.c5
-rw-r--r--drivers/char/tty_io.c14
-rw-r--r--drivers/net/3c501.c5
-rw-r--r--drivers/net/3c507.c1
-rw-r--r--drivers/net/3c509.c14
-rw-r--r--drivers/net/at1700.c5
-rw-r--r--drivers/net/atp.c789
-rw-r--r--drivers/net/atp.h264
-rw-r--r--drivers/net/eexpress.c11
-rw-r--r--drivers/net/hp.c473
-rw-r--r--drivers/net/iow.h122
-rw-r--r--drivers/net/lance.c30
-rw-r--r--drivers/net/ne.c13
-rw-r--r--drivers/net/skeleton.c3
-rw-r--r--drivers/scsi/aha152x.c21
-rw-r--r--drivers/scsi/fdomain.c34
-rw-r--r--drivers/sound/sb16_dsp.c2
-rw-r--r--fs/minix/inode.c89
-rw-r--r--include/asm/io.h18
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/mcd.h2
-rw-r--r--include/linux/minix_fs.h5
-rw-r--r--include/linux/minix_fs_sb.h3
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/ksyms.sh4
-rw-r--r--kernel/sched.c6
-rw-r--r--kernel/traps.c7
-rw-r--r--net/inet/icmp.c7
-rw-r--r--net/inet/ip.c20
-rw-r--r--net/inet/route.c49
-rw-r--r--net/inet/tcp.c3
-rw-r--r--net/inet/udp.c3
-rw-r--r--net/socket.c4
-rw-r--r--net/unix/proc.c1
38 files changed, 1526 insertions, 528 deletions
diff --git a/Makefile b/Makefile
index dbbe935..044c675 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 0.99
PATCHLEVEL = 14
-ALPHA = i
+ALPHA = k
all: Version zImage
@@ -189,8 +189,7 @@ zdisk: zImage
zlilo: $(CONFIGURE) zImage
if [ -f /vmlinuz ]; then mv /vmlinuz /vmlinuz.old; fi
cat zImage > /vmlinuz
- /etc/lilo/install
-
+ if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs
$(LD) $(LDFLAGS) -T 100000 boot/head.o init/main.o tools/version.o \
@@ -221,6 +220,7 @@ net: dummy
$(MAKE) linuxsubdirs SUBDIRS=net
clean:
+ rm -f kernel/ksyms.lst
rm -f core `find . -name '*.[oas]' -print`
rm -f core `find . -name 'core' -print`
rm -f zImage zSystem.map tools/zSystem tools/system
diff --git a/config.in b/config.in
index aed82ea..75a3812 100644
--- a/config.in
+++ b/config.in
@@ -82,7 +82,7 @@ bool 'AT1700 support' CONFIG_AT1700 n
#bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n
#bool 'Cabletron E21xx support (not recommended)' CONFIG_E21 n
bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
-#bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
+bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
fi
*
bool 'Sony CDU31A CDROM driver support' CONFIG_CDU31A n
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index b4dd66a..4391cc3 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -85,12 +85,6 @@ static struct hd_struct hd[MAX_HD<<6]={{0,0},};
static int hd_sizes[MAX_HD<<6] = {0, };
static int hd_blocksizes[MAX_HD<<6] = {0, };
-#define port_read(port,buf,nr) \
-__asm__("cld;rep;insw": :"d" (port),"D" (buf),"c" (nr):"cx","di")
-
-#define port_write(port,buf,nr) \
-__asm__("cld;rep;outsw": :"d" (port),"S" (buf),"c" (nr):"cx","si")
-
#if (HD_DELAY > 0)
unsigned long read_timer(void)
{
@@ -339,7 +333,7 @@ static void read_intr(void)
do_hd_request();
return;
ok_to_read:
- port_read(HD_DATA,CURRENT->buffer,256);
+ insw(HD_DATA,CURRENT->buffer,256);
CURRENT->errors = 0;
CURRENT->buffer += 512;
CURRENT->sector++;
@@ -398,7 +392,7 @@ ok_to_write:
end_request(1);
if (i > 0) {
SET_INTR(&write_intr);
- port_write(HD_DATA,CURRENT->buffer,256);
+ outsw(HD_DATA,CURRENT->buffer,256);
sti();
} else {
#if (HD_DELAY > 0)
@@ -508,7 +502,7 @@ repeat:
bad_rw_intr();
goto repeat;
}
- port_write(HD_DATA,CURRENT->buffer,256);
+ outsw(HD_DATA,CURRENT->buffer,256);
sti();
return;
}
diff --git a/drivers/char/console.c b/drivers/char/console.c
index a19a7a5..0823dc7 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -233,8 +233,8 @@ static unsigned char * translations[] = {
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
- "\004\261\007\007\007\007\370\361\040\007\331\277\332\300\305\007"
- "\007\304\007\007\303\264\301\302\263\007\007\007\007\007\234\0"
+ "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
+ "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index cb7a649..c25c17b 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -25,6 +25,7 @@
#include <linux/serial.h>
#include <linux/interrupt.h>
#include <linux/config.h>
+#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
@@ -1580,7 +1581,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
* If this is a callout device, then just make sure the normal
* device isn't being used.
*/
- if (MAJOR(filp->f_rdev) == 5) {
+ if (MAJOR(filp->f_rdev) == TTYAUX_MAJOR) {
if (info->flags & ASYNC_NORMAL_ACTIVE)
return -EBUSY;
if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
@@ -1694,7 +1695,7 @@ int rs_open(struct tty_struct *tty, struct file * filp)
tty->start = rs_start;
tty->hangup = rs_hangup;
if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
- if (MAJOR(filp->f_rdev) == 4)
+ if (MAJOR(filp->f_rdev) == TTY_MAJOR)
*tty->termios = info->normal_termios;
else
*tty->termios = info->callout_termios;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 1a2ac8b..44f094b 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -55,6 +55,8 @@
#include "vt_kern.h"
+#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
+
#define MAX_TTYS 256
struct tty_struct *tty_table[MAX_TTYS];
@@ -239,13 +241,13 @@ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops)
if (!tty)
return;
- dev = 0x0400 + tty->line;
+ dev = MKDEV(TTY_MAJOR,tty->line);
for (filp = first_file, i=0; i<nr_files; i++, filp = filp->f_next) {
- if (!filp->f_count)
+ if (!filp->f_count)
continue;
if (filp->f_rdev != dev)
continue;
- if (filp->f_inode && filp->f_inode->i_rdev == 0x0400)
+ if (filp->f_inode && filp->f_inode->i_rdev == CONSOLE_DEV)
continue;
if (filp->f_op != &tty_fops)
continue;
@@ -1031,7 +1033,7 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
tty = TTY_TABLE(dev);
if (!tty || (tty->flags & (1 << TTY_IO_ERROR)))
return -EIO;
- if ((inode->i_rdev != 0x0400) && /* don't stop on /dev/console */
+ if ((inode->i_rdev != CONSOLE_DEV) && /* don't stop on /dev/console */
(tty->pgrp > 0) &&
(current->tty == dev) &&
(tty->pgrp != current->pgrp))
@@ -1056,7 +1058,7 @@ static int tty_write(struct inode * inode, struct file * file, char * buf, int c
struct tty_struct * tty;
dev = file->f_rdev;
- is_console = (inode->i_rdev == 0x0400);
+ is_console = (inode->i_rdev == CONSOLE_DEV);
if (MAJOR(dev) != TTY_MAJOR) {
printk("tty_write: pseudo-major != TTY_MAJOR\n");
return -EINVAL;
@@ -1396,7 +1398,7 @@ static int tty_open(struct inode * inode, struct file * filp)
tty->session = current->session;
tty->pgrp = current->pgrp;
}
- filp->f_rdev = 0x0400 | minor; /* Set it to something normal */
+ filp->f_rdev = MKDEV(TTY_MAJOR,minor); /* Set it to something normal */
return 0;
}
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 44c5430..9b9d4db 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -38,7 +38,6 @@ static char *version =
#include <errno.h>
#include "dev.h"
-#include "iow.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
@@ -321,7 +320,7 @@ el_start_xmit(struct sk_buff *skb, struct device *dev)
inb(TX_STATUS);
outb(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */
outw(gp_start, GP_LOW);
- port_write_b(DATAPORT,buf,skb->len);
+ outsb(DATAPORT,buf,skb->len);
outw(gp_start, GP_LOW);
outb(AX_XMIT, AX_CMD); /* Trigger xmit. */
dev->trans_start = jiffies;
@@ -464,7 +463,7 @@ el_receive(struct device *dev)
skb->len = pkt_len;
skb->dev = dev;
- port_read_b(DATAPORT, (void *)(skb+1), pkt_len);
+ insb(DATAPORT, (void *)(skb+1), pkt_len);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 64c4532..f55131f 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -50,7 +50,6 @@ static char *version =
#include <memory.h>
#include "dev.h"
-#include "iow.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index f0898d2..d517cd4 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -33,16 +33,6 @@ static char *version = "3c509.c:pl13t 11/24/93 becker@super.org\n";
#include "skbuff.h"
#include "arp.h"
-#ifndef port_read
-#include "iow.h"
-#endif
-
-/* These should be in <asm/io.h>. */
-#define port_read_l(port,buf,nr) \
-__asm__("cld;rep;insl": :"d" (port),"D" (buf),"c" (nr):"cx","di")
-#define port_write_l(port,buf,nr) \
-__asm__("cld;rep;outsl": :"d" (port),"S" (buf),"c" (nr):"cx","si")
-
#ifndef HAVE_ALLOC_SKB
#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
#endif
@@ -415,7 +405,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
outw(skb->len, ioaddr + TX_FIFO);
outw(0x00, ioaddr + TX_FIFO);
/* ... and the packet rounded to a doubleword. */
- port_write_l(ioaddr + TX_FIFO, (void *)(skb+1), (skb->len + 3) >> 2);
+ outsl(ioaddr + TX_FIFO, (void *)(skb+1), (skb->len + 3) >> 2);
dev->trans_start = jiffies;
if (inw(ioaddr + TX_FREE) > 1536) {
@@ -588,7 +578,7 @@ el3_rx(struct device *dev)
skb->dev = dev;
/* 'skb+1' points to the start of sk_buff data area. */
- port_read_l(ioaddr+RX_FIFO, (void *)(skb+1),
+ insl(ioaddr+RX_FIFO, (void *)(skb+1),
(pkt_len + 3) >> 2);
#ifdef HAVE_NETIF_RX
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index fe619c8..d31cd66 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -38,7 +38,6 @@ static char *version =
#include <memory.h>
#include "dev.h"
-#include "iow.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
@@ -426,7 +425,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
outb(0x00, ioaddr + TX_INTR);
outw(length, ioaddr + DATAPORT);
- port_write(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
lp->tx_queue++;
lp->tx_queue_len += length + 2;
@@ -553,7 +552,7 @@ net_rx(struct device *dev)
skb->dev = dev;
/* 'skb+1' points to the start of sk_buff data area. */
- port_read(ioaddr + DATAPORT, (void *)(skb+1), (pkt_len + 1) >> 1);
+ insw(ioaddr + DATAPORT, (void *)(skb+1), (pkt_len + 1) >> 1);
if (net_debug > 5) {
int i;
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
new file mode 100644
index 0000000..f753c79
--- /dev/null
+++ b/drivers/net/atp.c
@@ -0,0 +1,789 @@
+/* atp.c: Attached (pocket) ethernet adaptor driver for linux. */
+/*
+ Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the Director,
+ National Security Agency. This software may only be used and distributed
+ according to the terms of the GNU Public License as modified by SRC,
+ incorported herein by reference.
+
+ The author may be reached as becker@super.org or
+ C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+
+*/
+
+static char *version =
+ "atp.c:v0.02 12/22/93 Donald Becker (becker@super.org)\n";
+
+/*
+ This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket
+ ethernet adaptor. This is a common low-cost OEM pocket ethernet
+ adaptor, sold under many names.
+
+ Sources:
+ This driver was written from the packet driver assembly code provided by
+ Vincent Bono of AT-Lan-Tec. Ever try to figure out how a complicated
+ device works just from the assembly code? It ain't pretty. The following
+ description is written based on guesses and writing lots of special-purpose
+ code to test my theorized operation.
+
+ Theory of Operation
+
+ The RTL8002 adaptor seems to be built around a custom spin of the SEEQ
+ controller core. It probably has a 16K or 64K internal packet buffer, of
+ which the first 4K is devoted to transmit and the rest to receive.
+ The controller maintains the queue of received packet and the packet buffer
+ access pointer internally, with only 'reset to beginning' and 'skip to next
+ packet' commands visible. The transmit packet queue holds two (or more?)
+ packets: both 'retransmit this packet' (due to collision) and 'transmit next
+ packet' commands must be started by hand.
+
+ The station address is stored in a standard bit-serial EEPROM which must be
+ read (ughh) by the device driver. (Provisions have been made for
+ substituting a 74S288 PROM, but I haven't gotten reports of any models
+ using it.) Unlike built-in devices, a pocket adaptor can temporarily lose
+ power without indication to the device driver. The major effect is that
+ the station address, receive filter (promiscuous, etc.) and transceiver
+ must be reset.
+
+ The controller itself has 16 registers, some of which use only the lower
+ bits. The registers are read and written 4 bits at a time. The four bit
+ register address is presented on the data lines along with a few additional
+ timing and control bits. The data is then read from status port or written
+ to the data port.
+
+ Since the bulk data transfer of the actual packets through the slow
+ parallel port dominates the driver's running time, four distinct data
+ (non-register) transfer modes are provided by the adaptor, two in each
+ direction. In the first mode timing for the nibble transfers is
+ provided through the data port. In the second mode the same timing is
+ provided through the control port. In either case the data is read from
+ the status port and written to the data port, just as it is accessing
+ registers.
+
+ In addition to the basic data transfer methods, several more are modes are
+ created by adding some delay by doing multiple reads of the data to allow
+ it to stabilize. This delay seems to be needed on most machines.
+
+ The data transfer mode is stored in the 'dev->if_port' field. Its default
+ value is '4'. It may be overriden at boot-time using the third parameter
+ to the "ether=..." initialization.
+
+ The header file <atp.h> provides inline functions that encapsulate the
+ register and data access methods. These functions are hand-tuned to
+ generate reasonable object code. This header file also documents my
+ interpretations of the device registers.
+*/
+
+#include <linux/config.h> /* Used only to override default values. */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#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 "dev.h"
+#include "eth.h"
+#include "skbuff.h"
+#include "arp.h"
+
+#include "atp.h"
+
+/* Compatibility definitions for earlier kernel versions. */
+#ifndef HAVE_AUTOIRQ
+/* From auto_irq.c, in ioport.h for later versions. */
+extern void autoirq_setup(int waittime);
+extern int autoirq_report(int waittime);
+/* The map from IRQ number (as passed to the interrupt handler) to
+ 'struct device'. */
+extern struct device *irq2dev_map[16];
+#endif
+
+#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
+
+#ifndef HAVE_PORTRESERVE
+#define check_region(ioaddr, size) 0
+#define snarf_region(ioaddr, size); do ; while (0)
+#endif
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 4
+#endif
+static unsigned int net_debug = NET_DEBUG;
+
+/* The number of low I/O ports used by the ethercard. */
+#define ETHERCARD_TOTAL_SIZE 3
+
+/* Index to functions, as function prototypes. */
+
+extern int atp_probe(struct device *dev);
+
+static int atp_probe1(struct device *dev, short ioaddr);
+static void init_dev(struct device *dev);
+static void get_node_ID(struct device *dev);
+static unsigned short eeprom_op(short ioaddr, unsigned int cmd);
+static int net_open(struct device *dev);
+static void hardware_init(struct device *dev);
+static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
+static void trigger_send(short ioaddr, int length);
+static int net_send_packet(struct sk_buff *skb, struct device *dev);
+static void net_interrupt(int reg_ptr);
+static void net_rx(struct device *dev);
+static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
+static int net_close(struct device *dev);
+static struct enet_statistics *net_get_stats(struct device *dev);
+#ifdef HAVE_MULTICAST
+static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+#endif
+
+
+/* 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, alloate space for the device and return success
+ (detachable devices only).
+ */
+int
+atp_init(struct device *dev)
+{
+ int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
+ int base_addr = dev->base_addr;
+
+ if (base_addr > 0x1ff) /* Check a single specified location. */
+ return atp_probe1(dev, base_addr);
+ else if (base_addr == 1) /* Don't probe at all. */
+ return ENXIO;
+
+ for (port = ports; *port; port++) {
+ int ioaddr = *port;
+ outb(0x57, ioaddr + PAR_DATA);
+ if (inb(ioaddr + PAR_DATA) != 0x57)
+ continue;
+ if (atp_probe1(dev, ioaddr) == 0)
+ return 0;
+ }
+
+ return ENODEV;
+}
+
+static int atp_probe1(struct device *dev, short ioaddr)
+{
+ int saved_ctrl_reg, status;
+
+ outb(0xff, ioaddr + PAR_DATA);
+ /* Save the original value of the Control register, in case we guessed
+ wrong. */
+ saved_ctrl_reg = inb(ioaddr + PAR_CONTROL);
+ /* IRQEN=0, SLCTB=high INITB=high, AUTOFDB=high, STBB=high. */
+ outb(0x04, ioaddr + PAR_CONTROL);
+ write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+ eeprom_delay(2048);
+ status = read_nibble(ioaddr, CMR1);
+
+ if ((status & 0x78) != 0x08) {
+ /* The pocket adaptor probe failed, restore the control register. */
+ outb(saved_ctrl_reg, ioaddr + PAR_CONTROL);
+ return 1;
+ }
+ status = read_nibble(ioaddr, CMR2_h);
+ if ((status & 0x78) != 0x10) {
+ outb(saved_ctrl_reg, ioaddr + PAR_CONTROL);
+ return 1;
+ }
+ /* Find the IRQ used by triggering an interrupt. */
+ write_reg_byte(ioaddr, CMR2, 0x01); /* No accept mode, IRQ out. */
+ write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE); /* Enable Tx and Rx. */
+
+ /* Omit autoIRQ routine for now. Use "table lookup" instead. Uhgggh. */
+ if (ioaddr == 0x378)
+ dev->irq = 7;
+ else
+ dev->irq = 5;
+ write_reg_high(ioaddr, CMR1, CMR1h_TxRxOFF); /* Diable Tx and Rx units. */
+ write_reg(ioaddr, CMR2, CMR2_NULL);
+
+ dev->base_addr = ioaddr;
+
+ /* Read the station address PROM. */
+ get_node_ID(dev);
+
+ printk("%s: Pocket adaptor found at %#3x, IRQ %d, SAPROM "
+ "%02X:%02X:%02X:%02X:%02X:%02X.\n", dev->name, dev->base_addr,
+ dev->irq, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+ /* Leave the hardware in a reset state. */
+ write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+
+ if (net_debug)
+ printk(version);
+
+ /* Initialize the device structure. */
+ init_dev(dev);
+ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+ memset(dev->priv, 0, sizeof(struct net_local));
+
+
+ {
+ struct net_local *lp = (struct net_local *)dev->priv;
+ lp->addr_mode = CMR2h_Normal;
+ }
+
+ /* For the ATP adaptor the "if_port" is really the data transfer mode. */
+ dev->if_port = (dev->mem_start & 0xf) ? dev->mem_start & 0x7 : 4;
+ if (dev->mem_end & 0xf)
+ net_debug = dev->mem_end & 7;
+
+ dev->open = net_open;
+ dev->stop = net_close;
+ dev->hard_start_xmit = net_send_packet;
+ dev->get_stats = net_get_stats;
+#ifdef HAVE_MULTICAST
+ dev->set_multicast_list = &set_multicast_list;
+#endif
+
+ return 0;
+}
+
+/* Fill in the fields of the device structure with ethernet-generic values.
+ This should be in a common file instead of per-driver. */
+static void init_dev(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < DEV_NUMBUFFS; i++)
+ dev->buffs[i] = NULL;
+
+ dev->hard_header = eth_header;
+ dev->add_arp = eth_add_arp;
+ dev->queue_xmit = dev_queue_xmit;
+ dev->rebuild_header = eth_rebuild_header;
+ dev->type_trans = eth_type_trans;
+
+ dev->type = ARPHRD_ETHER;
+ dev->hard_header_len = ETH_HLEN;
+ dev->mtu = 1500; /* eth_mtu */
+ dev->addr_len = ETH_ALEN;
+ for (i = 0; i < ETH_ALEN; i++) {
+ dev->broadcast[i]=0xff;
+ }
+
+ /* New-style flags. */
+ dev->flags = IFF_BROADCAST;
+ dev->family = AF_INET;
+ dev->pa_addr = 0;
+ dev->pa_brdaddr = 0;
+ dev->pa_mask = 0;
+ dev->pa_alen = sizeof(unsigned long);
+}
+
+/* Read the station address PROM, usually a word-wide EEPROM. */
+static void get_node_ID(struct device *dev)
+{
+ short ioaddr = dev->base_addr;
+ int sa_offset = 0;
+ int i;
+
+ write_reg(ioaddr, CMR2, CMR2_EEPROM); /* Point to the EEPROM control registers. */
+
+ /* Some adaptors have the station address at offset 15 instead of offset
+ zero. Check for it, and fix it if needed. */
+ if (eeprom_op(ioaddr, EE_READ(0)) == 0xffff)
+ sa_offset = 15;
+
+ for (i = 0; i < 3; i++)
+ ((unsigned short *)dev->dev_addr)[i] =
+ ntohs(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
+
+ write_reg(ioaddr, CMR2, CMR2_NULL);
+}
+
+/*
+ An EEPROM read command starts by shifting out 0x60+address, and then
+ shifting in the serial data. See the NatSemi databook for details.
+ * ________________
+ * CS : __|
+ * ___ ___
+ * CLK: ______| |___| |
+ * __ _______ _______
+ * DI : __X_______X_______X
+ * DO : _________X_______X
+ */
+
+static unsigned short eeprom_op(short ioaddr, unsigned int cmd)
+{
+ unsigned eedata_out = 0;
+ int num_bits = EE_CMD_SIZE;
+
+ while (--num_bits >= 0) {
+ char outval = test_bit(num_bits, &cmd) ? EE_DATA_WRITE : 0;
+ write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_LOW);
+ eeprom_delay(5);
+ write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_HIGH);
+ eedata_out <<= 1;
+ if (read_nibble(ioaddr, PROM_DATA) & EE_DATA_READ)
+ eedata_out++;
+ eeprom_delay(5);
+ }
+ write_reg_high(ioaddr, PROM_CMD, EE_CLK_LOW & ~EE_CS);
+ return eedata_out;
+}
+
+
+/* Open/initialize the board. This is called (in the current kernel)
+ sometime after booting when the 'ifconfig' program is run.
+
+ This routine sets everything up anew at each open, even
+ registers that "should" only need to be set once at boot, so that
+ there is non-reboot way to recover if something goes wrong.
+
+ This is an attachable device: if there is no dev->priv entry then it wasn't
+ probed for at boot-time, and we need to probe for it again.
+ */
+static int net_open(struct device *dev)
+{
+
+ /* The interrupt line is turned off (tri-stated) when the device isn't in
+ use. That's especially important for "attached" interfaces where the
+ port or interrupt may be shared. */
+ if (irq2dev_map[dev->irq] != 0
+ || (irq2dev_map[dev->irq] = dev) == 0
+ || request_irq(dev->irq, &net_interrupt)) {
+ return -EAGAIN;
+ }
+
+ hardware_init(dev);
+ dev->start = 1;
+ return 0;
+}
+
+/* This routine resets the hardware. We initialize everything, assuming that
+ the hardware may have been temporarily detacted. */
+static void hardware_init(struct device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int i;
+
+ write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+
+ for (i = 0; i < 6; i++)
+ write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
+
+ write_reg_high(ioaddr, CMR2, lp->addr_mode);
+
+ if (net_debug > 2) {
+ printk("%s: Reset: current Rx mode %d.\n", dev->name,
+ (read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f);
+ }
+
+ write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+ write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
+
+ /* Enable the interrupt line from the serial port. */
+ outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+
+ /* Unmask the interesting interrupts. */
+ write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+ write_reg_high(ioaddr, IMR, ISRh_RxErr);
+
+ lp->tx_unit_busy = 0;
+ lp->pac_cnt_in_tx_buf = 0;
+ lp->saved_tx_size = 0;
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+}
+
+static void trigger_send(short ioaddr, int length)
+{
+ write_reg_byte(ioaddr, TxCNT0, length & 0xff);
+ write_reg(ioaddr, TxCNT1, length >> 8);
+ write_reg(ioaddr, CMR1, CMR1_Xmit);
+}
+
+static void write_packet(short ioaddr, int length, unsigned char *packet, int data_mode)
+{
+ length = (length + 1) & ~1; /* Round up to word length. */
+ outb(EOC+MAR, ioaddr + PAR_DATA);
+ if ((data_mode & 1) == 0) {
+ /* Write the packet out, starting with the write addr. */
+ outb(WrAddr+MAR, ioaddr + PAR_DATA);
+ do {
+ write_byte_mode0(ioaddr, *packet++);
+ } while (--length > 0) ;
+ } else {
+ /* Write the packet out in slow mode. */
+ unsigned char outbyte = *packet++;
+
+ outb(Ctrl_LNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+ outb(WrAddr+MAR, ioaddr + PAR_DATA);
+
+ outb((outbyte & 0x0f)|0x40, ioaddr + PAR_DATA);
+ outb(outbyte & 0x0f, ioaddr + PAR_DATA);
+ outbyte >>= 4;
+ outb(outbyte & 0x0f, ioaddr + PAR_DATA);
+ outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+ while (--length > 0)
+ write_byte_mode1(ioaddr, *packet++);
+ }
+ /* Terminate the Tx frame. End of write: ECB. */
+ outb(0xff, ioaddr + PAR_DATA);
+ outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+}
+
+static int
+net_send_packet(struct sk_buff *skb, struct device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if (dev->tbusy) {
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ int tickssofar = jiffies - dev->trans_start;
+ if (tickssofar < 5)
+ return 1;
+ printk("%s: transmit timed out, %s?\n", dev->name,
+ inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
+ : "IRQ conflict");
+ lp->stats.tx_errors++;
+ /* Try to restart the adaptor. */
+ hardware_init(dev);
+ dev->tbusy=0;
+ dev->trans_start = jiffies;
+ }
+
+ /* If some higher layer thinks we've missed an tx-done interrupt
+ we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+ itself. */
+ if (skb == NULL) {
+ dev_tint(dev);
+ return 0;
+ }
+
+ /* 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+1, dev)) {
+ skb->dev = dev;
+ arp_queue (skb);
+ return 0;
+ }
+ skb->arp=1;
+
+ /* Block a timer-based transmit from overlapping. This could better be
+ done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+ if (set_bit(0, (void*)&dev->tbusy) != 0)
+ printk("%s: Transmitter access conflict.\n", dev->name);
+ else {
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = (void *)(skb+1);
+ int flags;
+
+ /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
+ This sequence must not be interrupted by an incoming packet. */
+ save_flags(flags);
+ cli();
+ write_reg(ioaddr, IMR, 0);
+ write_reg_high(ioaddr, IMR, 0);
+ restore_flags(flags);
+
+ write_packet(ioaddr, length, buf, dev->if_port);
+
+ lp->pac_cnt_in_tx_buf++;
+ if (lp->tx_unit_busy == 0) {
+ trigger_send(ioaddr, length);
+ lp->saved_tx_size = 0; /* Redundent */
+ lp->re_tx = 0;
+ lp->tx_unit_busy = 1;
+ } else
+ lp->saved_tx_size = length;
+
+ dev->trans_start = jiffies;
+ /* Re-enable the LPT interrupts. */
+ write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+ write_reg_high(ioaddr, IMR, ISRh_RxErr);
+ }
+
+ if (skb->free)
+ kfree_skb (skb, FREE_WRITE);
+
+ return 0;
+}
+
+/* The typical workload of the driver:
+ Handle the network interface interrupts. */
+static void
+net_interrupt(int reg_ptr)
+{
+ int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
+ struct device *dev = (struct device *)(irq2dev_map[irq]);
+ struct net_local *lp;
+ int ioaddr, status, boguscount = 20;
+ static int num_tx_since_rx = 0;
+
+ if (dev == NULL) {
+ printk ("ATP_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
+ dev->interrupt = 1;
+
+ ioaddr = dev->base_addr;
+ lp = (struct net_local *)dev->priv;
+
+ /* Disable additional spurious interrupts. */
+ outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
+
+ /* The adaptor's output is currently the IRQ line, switch it to data. */
+ write_reg(ioaddr, CMR2, CMR2_NULL);
+ write_reg(ioaddr, IMR, 0);
+
+ if (net_debug > 5) printk("%s: In interrupt ", dev->name);
+ while (--boguscount > 0) {
+ status = read_nibble(ioaddr, ISR);
+ if (net_debug > 5) printk("loop status %02x..", status);
+
+ if (status & (ISR_RxOK<<3)) {
+ write_reg(ioaddr, ISR, ISR_RxOK); /* Clear the Rx interrupt. */
+ do {
+ int read_status = read_nibble(ioaddr, CMR1);
+ if (net_debug > 6)
+ printk("handling Rx packet %02x..", read_status);
+ /* We acknowledged the normal Rx interrupt, so if the interrupt
+ is still outstanding we must have a Rx error. */
+ if (read_status & (CMR1_IRQ << 3)) { /* Overrun. */
+ lp->stats.rx_over_errors++;
+ /* Set to no-accept mode long enough to remove a packet. */
+ write_reg_high(ioaddr, CMR2, CMR2h_OFF);
+ net_rx(dev);
+ /* Clear the interrupt and return to normal Rx mode. */
+ write_reg_high(ioaddr, ISR, ISRh_RxErr);
+ write_reg_high(ioaddr, CMR2, lp->addr_mode);
+ } else if ((read_status & (CMR1_BufEnb << 3)) == 0) {
+ net_rx(dev);
+ dev->last_rx = jiffies;
+ num_tx_since_rx = 0;
+ } else
+ break;
+ } while (--boguscount > 0);
+ } else if (status & ((ISR_TxErr + ISR_TxOK)<<3)) {
+ if (net_debug > 6) printk("handling Tx done..");
+ /* Clear the Tx interrupt. We should check for too many failures
+ and reinitialize the adaptor. */
+ write_reg(ioaddr, ISR, ISR_TxErr + ISR_TxOK);
+ if (status & (ISR_TxErr<<3)) {
+ lp->stats.collisions++;
+ if (++lp->re_tx > 15) {
+ lp->stats.tx_aborted_errors++;
+ hardware_init(dev);
+ break;
+ }
+ /* Attempt to retransmit. */
+ if (net_debug > 6) printk("attempting to ReTx");
+ write_reg(ioaddr, CMR1, CMR1_ReXmit + CMR1_Xmit);
+ } else {
+ /* Finish up the transmit. */
+ lp->stats.tx_packets++;
+ lp->pac_cnt_in_tx_buf--;
+ if ( lp->saved_tx_size) {
+ trigger_send(ioaddr, lp->saved_tx_size);
+ lp->saved_tx_size = 0;
+ lp->re_tx = 0;
+ } else
+ lp->tx_unit_busy = 0;
+ dev->tbusy = 0;
+ mark_bh(INET_BH); /* Inform upper layers. */
+ }
+ num_tx_since_rx++;
+ } else if (num_tx_since_rx > 8
+ && jiffies > dev->last_rx + 100) {
+ if (net_debug > 2)
+ printk("%s: Missed packet? No Rx after %d Tx and %d jiffies"
+ " status %02x CMR1 %02x.\n", dev->name,
+ num_tx_since_rx, jiffies - dev->last_rx, status,
+ (read_nibble(ioaddr, CMR1) >> 3) & 15);
+ lp->stats.rx_missed_errors++;
+ hardware_init(dev);
+ num_tx_since_rx = 0;
+ break;
+ } else
+ break;
+ }
+
+ /* Tell the adaptor that it can go back to using the output line as IRQ. */
+ write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+ /* Enable the physical interrupt line, which is sure to be low until.. */
+ outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+ /* .. we enable the interrupt sources. */
+ write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+ write_reg_high(ioaddr, IMR, ISRh_RxErr); /* Hmmm, really needed? */
+
+ if (net_debug > 5) printk("exiting interrupt.\n");
+
+ dev->interrupt = 0;
+
+ return;
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void net_rx(struct device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+#ifdef notdef
+ ushort header[4];
+#else
+ struct rx_header rx_head;
+#endif
+
+ /* Process the received packet. */
+ outb(EOC+MAR, ioaddr + PAR_DATA);
+ read_block(ioaddr, 8, (unsigned char*)&rx_head, dev->if_port);
+ if (net_debug > 5)
+ printk(" rx_count %04x %04x %04x %04x..", rx_head.pad,
+ rx_head.rx_count, rx_head.rx_status, rx_head.cur_addr);
+ if ((rx_head.rx_status & 0x77) != 0x01) {
+ lp->stats.rx_errors++;
+ /* Ackkk! I don't have any documentation on what the error bits mean!
+ The best I can do is slap the device around a bit. */
+ if (net_debug > 3) printk("%s: Unknown ATP Rx error %04x.\n",
+ dev->name, rx_head.rx_status);
+ hardware_init(dev);
+ return;
+ } else {
+ /* Malloc up new buffer. */
+ int pkt_len = (rx_head.rx_count & 0x7ff) - 4; /* The "-4" is omits the FCS (CRC). */
+ int sksize = sizeof(struct sk_buff) + pkt_len;
+ struct sk_buff *skb;
+
+ skb = alloc_skb(sksize, GFP_ATOMIC);
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ goto done;
+ }
+ skb->mem_len = sksize;
+ skb->mem_addr = skb;
+ skb->len = pkt_len;
+ skb->dev = dev;
+
+ /* '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 = (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],
+ data[12], data[13]);
+ }
+
+#ifdef HAVE_NETIF_RX
+ netif_rx(skb);
+#else
+ skb->lock = 0;
+ if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {
+ kfree_s(skb, sksize);
+ lp->stats.rx_dropped++;
+ break;
+ }
+#endif
+ lp->stats.rx_packets++;
+ }
+ done:
+ write_reg(ioaddr, CMR1, CMR1_NextPkt);
+ return;
+}
+
+static void read_block(short ioaddr, int length, unsigned char *p, int data_mode)
+{
+
+ if (data_mode <= 3) { /* Mode 0 or 1 */
+ outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
+ outb(length == 8 ? RdAddr | HNib | MAR : RdAddr | MAR,
+ ioaddr + PAR_DATA);
+ if (data_mode <= 1) { /* Mode 0 or 1 */
+ do *p++ = read_byte_mode0(ioaddr); while (--length > 0);
+ } else /* Mode 2 or 3 */
+ do *p++ = read_byte_mode2(ioaddr); while (--length > 0);
+ } else if (data_mode <= 5)
+ do *p++ = read_byte_mode4(ioaddr); while (--length > 0);
+ else
+ do *p++ = read_byte_mode6(ioaddr); while (--length > 0);
+
+ outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
+ outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
+}
+
+/* The inverse routine to net_open(). */
+static int
+net_close(struct device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ /* Flush the Tx and disable Rx here. */
+ lp->addr_mode = CMR2h_OFF;
+ write_reg_high(ioaddr, CMR2, CMR2h_OFF);
+
+ /* Free the IRQ line. */
+ outb(0x00, ioaddr + PAR_CONTROL);
+ free_irq(dev->irq);
+ irq2dev_map[dev->irq] = 0;
+
+ /* Leave the hardware in a reset state. */
+ write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+
+ return 0;
+}
+
+/* Get the current statistics. This may be called with the card open or
+ closed. */
+static struct enet_statistics *
+net_get_stats(struct device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ return &lp->stats;
+}
+
+#ifdef HAVE_MULTICAST
+/* Set or clear the multicast filter for this adaptor.
+ num_addrs == -1 Promiscuous mode, receive all packets
+ num_addrs == 0 Normal mode, clear multicast list
+ num_addrs > 0 Multicast mode, receive normal and MC packets, and do
+ best-effort filtering.
+ */
+static void
+set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ short ioaddr = dev->base_addr;
+ lp->addr_mode = num_addrs ? CMR2h_PROMISC : CMR2h_Normal;
+ write_reg_high(ioaddr, CMR2, lp->addr_mode);
+}
+#endif
+
+/*
+ * Local variables:
+ * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c atp.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * tab-width: 4
+ * End:
+ */
diff --git a/drivers/net/atp.h b/drivers/net/atp.h
new file mode 100644
index 0000000..6988eae
--- /dev/null
+++ b/drivers/net/atp.h
@@ -0,0 +1,264 @@
+#include <linux/if_ether.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+struct net_local {
+#ifdef __KERNEL__
+ struct enet_statistics stats;
+#endif
+ ushort saved_tx_size;
+ unsigned char
+ re_tx, /* Number of packet retransmissions. */
+ tx_unit_busy,
+ addr_mode, /* Current Rx filter e.g. promiscuous, etc. */
+ pac_cnt_in_tx_buf;
+};
+
+struct rx_header {
+ ushort pad; /* The first read is always corrupted. */
+ ushort rx_count;
+ ushort rx_status; /* Unknown bit assignments :-<. */
+ ushort cur_addr; /* Apparently the current buffer address(?) */
+};
+
+#define PAR_DATA 0
+#define PAR_STATUS 1
+#define PAR_CONTROL 2
+
+#define Ctrl_LNibRead 0x08 /* LP_PSELECP */
+#define Ctrl_HNibRead 0
+#define Ctrl_LNibWrite 0x08 /* LP_PSELECP */
+#define Ctrl_HNibWrite 0
+#define Ctrl_SelData 0x04 /* LP_PINITP */
+#define Ctrl_IRQEN 0x10 /* LP_PINTEN */
+
+#define EOW 0xE0
+#define EOC 0xE0
+#define WrAddr 0x40 /* Set address of EPLC read, write register. */
+#define RdAddr 0xC0
+#define HNib 0x10
+
+enum page0_regs
+{
+ /* The first six registers hold the ethernet physical station address. */
+ PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5,
+ TxCNT0 = 6, TxCNT1 = 7, /* The transmit byte count. */
+ TxSTAT = 8, RxSTAT = 9, /* Tx and Rx status. */
+ ISR = 10, IMR = 11, /* Interrupt status and mask. */
+ CMR1 = 12, /* Command register 1. */
+ CMR2 = 13, /* Command register 2. */
+ MAR = 14, /* Memory address register. */
+ CMR2_h = 0x1d, };
+
+enum eepage_regs
+{ PROM_CMD = 6, PROM_DATA = 7 }; /* Note that PROM_CMD is in the "high" bits. */
+
+
+#define ISR_TxOK 0x01
+#define ISR_RxOK 0x04
+#define ISR_TxErr 0x02
+#define ISRh_RxErr 0x11 /* ISR, high nibble */
+
+#define CMR1h_RESET 0x04 /* Reset. */
+#define CMR1h_RxENABLE 0x02 /* Rx unit enable. */
+#define CMR1h_TxENABLE 0x01 /* Tx unit enable. */
+#define CMR1h_TxRxOFF 0x00
+#define CMR1_ReXmit 0x08 /* Trigger a retransmit. */
+#define CMR1_Xmit 0x04 /* Trigger a transmit. */
+#define CMR1_IRQ 0x02 /* Interrupt active. */
+#define CMR1_BufEnb 0x01 /* Enable the buffer(?). */
+#define CMR1_NextPkt 0x01 /* Enable the buffer(?). */
+
+#define CMR2_NULL 8
+#define CMR2_IRQOUT 9
+#define CMR2_RAMTEST 10
+#define CMR2_EEPROM 12 /* Set to page 1, for reading the EEPROM. */
+
+#define CMR2h_OFF 0 /* No accept mode. */
+#define CMR2h_Physical 1 /* Accept a physical address match only. */
+#define CMR2h_Normal 2 /* Accept physical and broadcast address. */
+#define CMR2h_PROMISC 3 /* Promiscuous mode. */
+
+/* An inline function used below: it differs from inb() by explicitly return an unsigned
+ char, saving a truncation. */
+extern inline unsigned char inbyte(unsigned short port)
+{
+ unsigned char _v;
+ __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port));
+ return _v;
+}
+
+/* Read register OFFSET.
+ This command should aways be terminated with read_end(). */
+extern inline unsigned char read_nibble(short port, unsigned char offset)
+{
+ unsigned char retval;
+ outb(EOC+offset, port + PAR_DATA);
+ outb(RdAddr+offset, port + PAR_DATA);
+ inbyte(port + PAR_STATUS); /* Settling time delay */
+ retval = inbyte(port + PAR_STATUS);
+ outb(EOC+offset, port + PAR_DATA);
+
+ return retval;
+}
+
+/* Functions for bulk data read. The interrupt line is always disabled. */
+/* Get a byte using read mode 0, reading data from the control lines. */
+extern inline unsigned char read_byte_mode0(short ioaddr)
+{
+ unsigned char low_nib;
+
+ outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
+ inbyte(ioaddr + PAR_STATUS);
+ low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
+ outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL);
+ inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */
+ inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */
+ return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
+}
+
+/* The same as read_byte_mode0(), but does multiple inb()s for stability. */
+extern inline unsigned char read_byte_mode2(short ioaddr)
+{
+ unsigned char low_nib;
+
+ outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
+ inbyte(ioaddr + PAR_STATUS);
+ low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
+ outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL);
+ inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */
+ return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
+}
+
+/* Read a byte through the data register. */
+extern inline unsigned char read_byte_mode4(short ioaddr)
+{
+ unsigned char low_nib;
+
+ outb(RdAddr | MAR, ioaddr + PAR_DATA);
+ low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
+ outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA);
+ return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
+}
+
+/* Read a byte through the data register, double reading to allow settling. */
+extern inline unsigned char read_byte_mode6(short ioaddr)
+{
+ unsigned char low_nib;
+
+ outb(RdAddr | MAR, ioaddr + PAR_DATA);
+ inbyte(ioaddr + PAR_STATUS);
+ low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
+ outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA);
+ inbyte(ioaddr + PAR_STATUS);
+ return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
+}
+
+extern inline void
+write_reg(short port, unsigned char reg, unsigned char value)
+{
+ unsigned char outval;
+ outb(EOC | reg, port + PAR_DATA);
+ outval = WrAddr | reg;
+ outb(outval, port + PAR_DATA);
+ outb(outval, port + PAR_DATA); /* Double write for PS/2. */
+
+ outval &= 0xf0;
+ outval |= value;
+ outb(outval, port + PAR_DATA);
+ outval &= 0x1f;
+ outb(outval, port + PAR_DATA);
+ outb(outval, port + PAR_DATA);
+
+ outb(EOC | outval, port + PAR_DATA);
+}
+
+extern inline void
+write_reg_high(short port, unsigned char reg, unsigned char value)
+{
+ unsigned char outval = EOC | HNib | reg;
+
+ outb(outval, port + PAR_DATA);
+ outval &= WrAddr | HNib | 0x0f;
+ outb(outval, port + PAR_DATA);
+ outb(outval, port + PAR_DATA); /* Double write for PS/2. */
+
+ outval = WrAddr | HNib | value;
+ outb(outval, port + PAR_DATA);
+ outval &= HNib | 0x0f; /* HNib | value */
+ outb(outval, port + PAR_DATA);
+ outb(outval, port + PAR_DATA);
+
+ outb(EOC | HNib | outval, port + PAR_DATA);
+}
+
+/* Write a byte out using nibble mode. The low nibble is written first. */
+extern inline void
+write_reg_byte(short port, unsigned char reg, unsigned char value)
+{
+ unsigned char outval;
+ outb(EOC | reg, port + PAR_DATA); /* Reset the address register. */
+ outval = WrAddr | reg;
+ outb(outval, port + PAR_DATA);
+ outb(outval, port + PAR_DATA); /* Double write for PS/2. */
+
+ outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA);
+ outb(value & 0x0f, port + PAR_DATA);
+ value >>= 4;
+ outb(value, port + PAR_DATA);
+ outb(0x10 | value, port + PAR_DATA);
+ outb(0x10 | value, port + PAR_DATA);
+
+ outb(EOC | value, port + PAR_DATA); /* Reset the address register. */
+}
+
+/*
+ * Bulk data writes to the packet buffer. The interrupt line remains enabled.
+ * The first, faster method uses only the dataport (data modes 0, 2 & 4).
+ * The second (backup) method uses data and control regs (modes 1, 3 & 5).
+ * It should only be needed when there is skew between the individual data
+ * lines.
+ */
+extern inline void write_byte_mode0(short ioaddr, unsigned char value)
+{
+ outb(value & 0x0f, ioaddr + PAR_DATA);
+ outb((value>>4) | 0x10, ioaddr + PAR_DATA);
+}
+
+extern inline void write_byte_mode1(short ioaddr, unsigned char value)
+{
+ outb(value & 0x0f, ioaddr + PAR_DATA);
+ outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL);
+ outb((value>>4) | 0x10, ioaddr + PAR_DATA);
+ outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL);
+}
+
+/* Write 16bit VALUE to the packet buffer: the same as above just doubled. */
+extern inline void write_word_mode0(short ioaddr, unsigned short value)
+{
+ outb(value & 0x0f, ioaddr + PAR_DATA);
+ value >>= 4;
+ outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA);
+ value >>= 4;
+ outb(value & 0x0f, ioaddr + PAR_DATA);
+ value >>= 4;
+ outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA);
+}
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_CLK_HIGH 0x12
+#define EE_CLK_LOW 0x16
+#define EE_DATA_WRITE 0x01 /* EEPROM chip data in. */
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+
+/* Delay between EEPROM clock transitions. */
+#define eeprom_delay(ticks) \
+do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD(offset) (((5 << 6) + (offset)) << 17)
+#define EE_READ(offset) (((6 << 6) + (offset)) << 17)
+#define EE_ERASE(offset) (((7 << 6) + (offset)) << 17)
+#define EE_CMD_SIZE 27 /* The command+address+data size. */
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 41c2480..7daab32 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -50,7 +50,6 @@ static char *version =
#include <memory.h>
#include "dev.h"
-#include "iow.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
@@ -701,7 +700,7 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
by the list of multicast addresses to be accepted. */
outw(SET_MC_CMD + 6, ioaddr + WRITE_PTR);
outw(num_addrs * 6, ioaddr);
- port_write(ioaddr, addrs, num_addrs*3); /* 3 = addr len in words */
+ outsw(ioaddr, addrs, num_addrs*3); /* 3 = addr len in words */
/* We must trigger a whole 586 reset due to a bug. */
} else {
/* Not written yet, this requires expanding the init_words config
@@ -770,11 +769,11 @@ init_82586_mem(struct device *dev)
/* Place the write pointer at 0xfff6 (address-aliased to 0xfffff6). */
outw(0xfff6, ioaddr + WRITE_PTR);
- port_write(ioaddr, init_words, sizeof(init_words)>>1);
+ outsw(ioaddr, init_words, sizeof(init_words)>>1);
/* Fill in the station address. */
outw(SA_OFFSET, ioaddr + WRITE_PTR);
- port_write(ioaddr, dev->dev_addr, 3);
+ outsw(ioaddr, dev->dev_addr, 3);
/* The Tx-block list is written as needed. We just set up the values. */
#ifdef initial_text_tx
@@ -882,7 +881,7 @@ hardware_send_packet(struct device *dev, void *buf, short length)
/* Output the packet using the write pointer.
Hmmm, it feels a little like a 3c501! */
- port_write(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
/* Set the old command link pointing to this send packet. */
outw(lp->tx_cmd_link, ioaddr + WRITE_PTR);
@@ -961,7 +960,7 @@ eexp_rx(struct device *dev)
outw(data_buffer_addr + 10, ioaddr + READ_PTR);
- port_read(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
+ insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index f6304f1..eda01d1 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -1,19 +1,19 @@
/* hp.c: A HP LAN ethernet driver for linux. */
/*
- Written 1993 by Donald Becker.
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency. This software may be used and
- distributed according to the terms of the GNU Public License,
- incorporated herein by reference.
+ Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the
+ Director, National Security Agency. This software may be used and
+ distributed according to the terms of the GNU Public License,
+ incorporated herein by reference.
- This is a driver for the HP LAN adaptors.
+ This is a driver for the HP LAN adaptors.
- The Author may be reached as becker@super.org or
- C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+ The Author may be reached as becker@super.org or
+ C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
static char *version =
- "hp.c:v0.99.13f 10/16/93 Donald Becker (becker@super.org)\n";
+ "hp.c:v0.99.14a 12/2/93 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
@@ -22,182 +22,194 @@ static char *version =
#include <linux/ioport.h>
#include <asm/system.h>
#include <asm/io.h>
-#ifndef port_read
-#include "iow.h"
-#endif
#include "dev.h"
#include "8390.h"
-#define HP_DATAPORT 0x0c /* "Remote DMA" data port. */
-#define HP_ID 0x07
+#ifndef HAVE_PORTRESERVE
+#define check_region(ioaddr, size) 0
+#define snarf_region(ioaddr, size); do ; while (0)
+#endif
+
+#define HP_IO_EXTENT 32
+
+#define HP_DATAPORT 0x0c /* "Remote DMA" data port. */
+#define HP_ID 0x07
#define HP_CONFIGURE 0x08 /* Configuration register. */
-#define HP_RUN 0x01 /* 1 == Run, 0 == reset. */
-#define HP_IRQ 0x0E /* Mask for software-configured IRQ line. */
-#define HP_DATAON 0x10 /* Turn on dataport */
-#define NIC_OFFSET 0x10 /* Offset the 8390 registers. */
+#define HP_RUN 0x01 /* 1 == Run, 0 == reset. */
+#define HP_IRQ 0x0E /* Mask for software-configured IRQ line. */
+#define HP_DATAON 0x10 /* Turn on dataport */
+#define NIC_OFFSET 0x10 /* Offset the 8390 registers. */
-#define HP_START_PG 0x00 /* First page of TX buffer */
+#define HP_START_PG 0x00 /* First page of TX buffer */
#define HP_8BSTOP_PG 0x80 /* Last page +1 of RX ring */
-#define HP_16BSTOP_PG 0xFF /* Last page +1 of RX ring */
+#define HP_16BSTOP_PG 0xFF /* Same, for 16 bit cards. */
int hp_probe(struct device *dev);
-int hpprobe1(int ioaddr, struct device *dev);
+int hpprobe1(struct device *dev, int ioaddr);
static void hp_reset_8390(struct device *dev);
static int hp_block_input(struct device *dev, int count,
- char *buf, int ring_offset);
+ char *buf, int ring_offset);
static void hp_block_output(struct device *dev, int count,
- const unsigned char *buf, const start_page);
+ const unsigned char *buf, const start_page);
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};
-/* Probe for an HP LAN adaptor.
- Also initialize the card and fill in STATION_ADDR with the station
- address. */
+/* Probe for an HP LAN adaptor.
+ Also initialize the card and fill in STATION_ADDR with the station
+ address. */
int hp_probe(struct device *dev)
{
- int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
- short ioaddr = dev->base_addr;
+ int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
+ short ioaddr = dev->base_addr;
- if (ioaddr > 0x1ff) /* Check a single specified location. */
- return ! hpprobe1(ioaddr, dev);
- else if (ioaddr > 0) /* Don't probe at all. */
+ if (ioaddr > 0x1ff) /* Check a single specified location. */
+ return hpprobe1(dev, ioaddr);
+ else if (ioaddr > 0) /* Don't probe at all. */
return ENXIO;
- for (port = &ports[0]; *port; port++) {
-#ifdef HAVE_PORTRESERVE
- if (check_region(*port, 32))
- continue;
-#endif
- if (inb_p(*port) != 0xff && hpprobe1(*port, dev)) {
- return 0;
+ for (port = &ports[0]; *port; port++) {
+ if (check_region(*port, HP_IO_EXTENT))
+ continue;
+ if (hpprobe1(dev, *port) == 0) {
+ return 0;
+ }
}
- }
- dev->base_addr = ioaddr;
- return ENODEV;
+ return ENODEV;
}
-int hpprobe1(int ioaddr, struct device *dev)
+int hpprobe1(struct device *dev, int ioaddr)
{
- int i;
- unsigned char *station_addr = dev->dev_addr;
- int tmp;
-
- /* Check for the HP physical address, 08 00 09 xx xx xx. */
- if (inb(ioaddr) != 0x08
- || inb(ioaddr+1) != 0x00
- || inb(ioaddr+2) != 0x09)
- return 0;
- /* This really isn't good enough, we may pick up HP LANCE boards also! */
-
- ethdev_init(dev);
-
- ei_status.tx_start_page = HP_START_PG;
- ei_status.rx_start_page = HP_START_PG + TX_PAGES;
- /* Set up the rest of the parameters. */
- if ((tmp = inb(ioaddr + HP_ID)) & 0x80) {
- ei_status.name = "HP27247";
- ei_status.word16 = 1;
- ei_status.stop_page = HP_16BSTOP_PG; /* Safe (if small) value */
- } else {
- ei_status.name = "HP27250";
- ei_status.word16 = 0;
- ei_status.stop_page = HP_8BSTOP_PG;
- }
-
- printk("%s: %s at %#3x,", dev->name, ei_status.name, ioaddr);
-
- for(i = 0; i < ETHER_ADDR_LEN; i++)
- printk(" %2.2x", station_addr[i] = inb(ioaddr + i));
-
-
- /* Set the base address to point to the NIC, not the "real" base! */
- dev->base_addr = ioaddr + NIC_OFFSET;
-
- /* Snarf the interrupt now. Someday this could be moved to open(). */
- if (dev->irq < 2) {
- int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
- int irq_8list[] = { 7, 5, 3, 4, 9, 0};
- int *irqp = ei_status.word16 ? irq_16list : irq_8list;
- do {
- if (request_irq (dev->irq = *irqp, NULL) != -EBUSY) {
- autoirq_setup(0);
- /* Twinkle the interrupt, and check if it's seen. */
- outb_p(irqmap[dev->irq] | HP_RUN, ioaddr + HP_CONFIGURE);
- outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
- if (dev->irq == autoirq_report(0) /* It's a good IRQ line! */
- && request_irq (dev->irq, &ei_interrupt) == 0) {
- printk(" selecting IRQ %d.\n", dev->irq);
- break;
- }
- }
- } while (*++irqp);
- if (*irqp == 0) {
- printk(" no free IRQ lines.\n");
- return 0;
- }
- } else {
- if (dev->irq == 2)
- dev->irq = 9;
- if (irqaction(dev->irq, &ei_sigaction)) {
- printk (" unable to get IRQ %d.\n", dev->irq);
- return 0;
- }
- }
-
-#ifdef HAVE_PORTRESERVE
- snarf_region(ioaddr, 32);
-#endif
+ int status, 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. */
+ 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)
+ return ENODEV;
+
+ /* Set up the parameters based on the board ID.
+ If you have additional mappings, please mail them to becker@super.org. */
+ if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
+ name = "HP27247";
+ wordmode = 1;
+ } else {
+ name = "HP27250";
+ wordmode = 0;
+ }
+
+ /* Grab the region so we can find another board if something fails. */
+ snarf_region(ioaddr, HP_IO_EXTENT);
+
+ printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
+
+ for(i = 0; i < ETHER_ADDR_LEN; i++)
+ printk(" %2.2x", station_addr[i] = inb(ioaddr + i));
+
+ /* Snarf the interrupt now. Someday this could be moved to open(). */
+ if (dev->irq < 2) {
+ int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
+ int irq_8list[] = { 7, 5, 3, 4, 9, 0};
+ int *irqp = wordmode ? irq_16list : irq_8list;
+ do {
+ int irq = *irqp;
+ if (request_irq (irq, NULL) != -EBUSY) {
+ autoirq_setup(0);
+ /* Twinkle the interrupt, and check if it's seen. */
+ outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
+ outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
+ if (irq == autoirq_report(0) /* It's a good IRQ line! */
+ && request_irq (irq, &ei_interrupt) == 0) {
+ printk(" selecting IRQ %d.\n", irq);
+ dev->irq = *irqp;
+ break;
+ }
+ }
+ } while (*++irqp);
+ if (*irqp == 0) {
+ printk(" no free IRQ lines.\n");
+ return EBUSY;
+ }
+ } else {
+ if (dev->irq == 2)
+ dev->irq = 9;
+ if (irqaction(dev->irq, &ei_sigaction)) {
+ printk (" unable to get IRQ %d.\n", dev->irq);
+ return EBUSY;
+ }
+ }
+
+ if (ei_debug > 1)
+ printk(version);
- if (ei_debug > 1)
- printk(version);
+ /* Set the base address to point to the NIC, not the "real" base! */
+ dev->base_addr = ioaddr + NIC_OFFSET;
- ei_status.reset_8390 = &hp_reset_8390;
- ei_status.block_input = &hp_block_input;
- ei_status.block_output = &hp_block_output;
- hp_init_card(dev);
- return dev->base_addr;
+ ethdev_init(dev);
+
+ ei_status.name = name;
+ ei_status.word16 = wordmode;
+ ei_status.tx_start_page = HP_START_PG;
+ ei_status.rx_start_page = HP_START_PG + TX_PAGES;
+ ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
+
+ ei_status.reset_8390 = &hp_reset_8390;
+ ei_status.block_input = &hp_block_input;
+ ei_status.block_output = &hp_block_output;
+ hp_init_card(dev);
+
+ return 0;
}
static void
hp_reset_8390(struct device *dev)
{
- int hp_base = dev->base_addr - NIC_OFFSET;
- int saved_config = inb_p(hp_base + HP_CONFIGURE);
- int reset_start_time = jiffies;
-
- if (ei_debug > 1) printk("resetting the 8390 time=%d...", jiffies);
- outb_p(0x00, hp_base + HP_CONFIGURE);
- ei_status.txing = 0;
-
- sti();
- /* We shouldn't use the boguscount for timing, but this hasn't been
- checked yet, and you could hang your machine if jiffies break... */
- {
- int boguscount = 150000;
- while(jiffies - reset_start_time < 2)
- if (boguscount-- < 0) {
- printk("jiffy failure (t=%d)...", jiffies);
- break;
- }
- }
-
- outb_p(saved_config, hp_base + HP_CONFIGURE);
- while ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
- if (jiffies - reset_start_time > 2) {
- printk("%s: hp_reset_8390() did not complete.\n", dev->name);
- return;
+ int hp_base = dev->base_addr - NIC_OFFSET;
+ int saved_config = inb_p(hp_base + HP_CONFIGURE);
+ int reset_start_time = jiffies;
+
+ if (ei_debug > 1) printk("resetting the 8390 time=%d...", jiffies);
+ outb_p(0x00, hp_base + HP_CONFIGURE);
+ ei_status.txing = 0;
+
+ sti();
+ /* We shouldn't use the boguscount for timing, but this hasn't been
+ checked yet, and you could hang your machine if jiffies break... */
+ {
+ int boguscount = 150000;
+ while(jiffies - reset_start_time < 2)
+ if (boguscount-- < 0) {
+ printk("jiffy failure (t=%d)...", jiffies);
+ break;
+ }
}
- if (ei_debug > 1) printk("8390 reset done (%d).", jiffies);
+
+ outb_p(saved_config, hp_base + HP_CONFIGURE);
+ while ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
+ if (jiffies - reset_start_time > 2) {
+ printk("%s: hp_reset_8390() did not complete.\n", dev->name);
+ return;
+ }
+ if (ei_debug > 1) printk("8390 reset done (%d).", jiffies);
}
-/* Block input and output, similar to the Crynwr packet driver. If you
+/* Block input and output, similar to the Crynwr packet driver. If you
porting to a new ethercard look at the packet driver source for hints.
The HP LAN doesn't use shared memory -- we put the packet
out through the "remote DMA" dataport. */
@@ -205,111 +217,112 @@ hp_reset_8390(struct device *dev)
static int
hp_block_input(struct device *dev, int count, char *buf, int ring_offset)
{
- int nic_base = dev->base_addr;
- int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
- int xfer_count = count;
-
- outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
- outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base);
- if (ei_status.word16) {
- port_read(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1);
- if (count & 0x01)
- buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++;
- } else {
- port_read_b(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
- }
- /* This is for the ALPHA version only, remove for later releases. */
- if (ei_debug > 0) { /* DMA termination address check... */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- int addr = (high << 8) + low;
- /* Check only the lower 8 bits so we can ignore ring wrap. */
- if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff))
- printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n",
- dev->name, ring_offset + xfer_count, addr);
- }
- outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
- return ring_offset + count;
+ int nic_base = dev->base_addr;
+ int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+ int xfer_count = count;
+
+ outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
+ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+ outb_p(count >> 8, nic_base + EN0_RCNTHI);
+ outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base);
+ if (ei_status.word16) {
+ insw(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1);
+ if (count & 0x01)
+ buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++;
+ } else {
+ insb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
+ }
+ /* This is for the ALPHA version only, remove for later releases. */
+ if (ei_debug > 0) { /* DMA termination address check... */
+ int high = inb_p(nic_base + EN0_RSARHI);
+ int low = inb_p(nic_base + EN0_RSARLO);
+ int addr = (high << 8) + low;
+ /* Check only the lower 8 bits so we can ignore ring wrap. */
+ if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff))
+ printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n",
+ dev->name, ring_offset + xfer_count, addr);
+ }
+ outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+ return ring_offset + count;
}
static void
hp_block_output(struct device *dev, int count,
- const unsigned char *buf, const start_page)
+ const unsigned char *buf, const start_page)
{
- int nic_base = dev->base_addr;
- int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
-
- outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (ei_status.word16 && (count & 0x01))
- count++;
- /* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
+ int nic_base = dev->base_addr;
+ int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+
+ outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+ /* Round the count up for word writes. Do we need to do this?
+ What effect will an odd byte count have on the 8390?
+ I should check someday. */
+ if (ei_status.word16 && (count & 0x01))
+ count++;
+ /* We should already be in page 0, but to be safe... */
+ outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
#ifdef ei8390_bug
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work. */
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0xff, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, EN_CMD);
- /* Make certain that the dummy read has occured. */
- inb_p(0x61);
- inb_p(0x61);
+ /* Handle the read-before-write bug the same way as the
+ Crynwr packet driver -- the NatSemi method doesn't work. */
+ outb_p(0x42, nic_base + EN0_RCNTLO);
+ outb_p(0, nic_base + EN0_RCNTHI);
+ outb_p(0xff, nic_base + EN0_RSARLO);
+ outb_p(0x00, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, EN_CMD);
+ /* Make certain that the dummy read has occured. */
+ inb_p(0x61);
+ inb_p(0x61);
#endif
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(0x00, nic_base + EN0_RSARLO);
- outb_p(start_page, nic_base + EN0_RSARHI);
-
- outb_p(E8390_RWRITE+E8390_START, nic_base);
- if (ei_status.word16) {
- /* Use the 'rep' sequence for 16 bit boards. */
- port_write(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1);
- } else {
- port_write_b(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
- }
-
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */
-
- /* This is for the ALPHA version only, remove for later releases. */
- if (ei_debug > 0) { /* DMA termination address check... */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- int addr = (high << 8) + low;
- if ((start_page << 8) + count != addr)
- printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n",
- dev->name, (start_page << 8) + count, addr);
- }
- outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
- return;
+ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+ outb_p(count >> 8, nic_base + EN0_RCNTHI);
+ outb_p(0x00, nic_base + EN0_RSARLO);
+ outb_p(start_page, nic_base + EN0_RSARHI);
+
+ outb_p(E8390_RWRITE+E8390_START, nic_base);
+ if (ei_status.word16) {
+ /* Use the 'rep' sequence for 16 bit boards. */
+ outsw(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1);
+ } else {
+ outsb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
+ }
+
+ /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */
+
+ /* This is for the ALPHA version only, remove for later releases. */
+ if (ei_debug > 0) { /* DMA termination address check... */
+ int high = inb_p(nic_base + EN0_RSARHI);
+ int low = inb_p(nic_base + EN0_RSARLO);
+ int addr = (high << 8) + low;
+ if ((start_page << 8) + count != addr)
+ printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n",
+ dev->name, (start_page << 8) + count, addr);
+ }
+ outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+ return;
}
/* This function resets the ethercard if something screws up. */
static void
hp_init_card(struct device *dev)
{
- int irq = dev->irq;
- NS8390_init(dev, 0);
- outb_p(irqmap[irq&0x0f] | HP_RUN,
- dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
- return;
+ int irq = dev->irq;
+ NS8390_init(dev, 0);
+ outb_p(irqmap[irq&0x0f] | HP_RUN,
+ dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
+ return;
}
/*
* Local variables:
- * compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c hp.c"
+ * 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
* End:
*/
diff --git a/drivers/net/iow.h b/drivers/net/iow.h
index e186c45..6e15688 100644
--- a/drivers/net/iow.h
+++ b/drivers/net/iow.h
@@ -1,126 +1,6 @@
#ifndef _ASM_IOW_H
#define _ASM_IOW_H
-/* I added a few. Please add to the distributed files. -djb. */
-/* This file is copied 1:1 from /linux/include/asm/io.h, and changed all
- al to ax, all inb to inw and all outb to outw (to get word in/out)
- the four inlines here should be added to the original, and
- then this one rm'd (and the #include "iow.h" in depca.c removed)...
- Gruss PB
-*/
-/*
- * Thanks to James van Artsdalen for a better timing-fix than
- * the two short jumps: using outb's to a nonexistent port seems
- * to guarantee better timings even on fast machines.
- *
- * On the other hand, I'd like to be sure of a non-existent port:
- * I feel a bit unsafe abou using 0x80.
- *
- * Linus
- */
-/* This is the more general version of outw.. */
-extern inline void __outw(unsigned short value, unsigned short port)
-{
-__asm__ __volatile__ ("outw %w0,%w1"
- : /* no outputs */
- :"a" (value),"d" (port));
-}
-
-/* this is used for constant port numbers < 256.. */
-extern inline void __outwc(unsigned short value, unsigned short port)
-{
-__asm__ __volatile__ ("outw %w0,%1"
- : /* no outputs */
- :"a" (value),"i" (port));
-}
-
-/* general version of inw */
-extern inline unsigned int __inw(unsigned short port)
-{
- unsigned int _v;
-__asm__ __volatile__ ("inw %w1,%w0"
- :"=a" (_v):"d" (port),"0" (0));
- return _v;
-}
-
-/* inw with constant port nr 0-255 */
-extern inline unsigned int __inwc(unsigned short port)
-{
- unsigned int _v;
-__asm__ __volatile__ ("inw %1,%w0"
- :"=a" (_v):"i" (port),"0" (0));
- return _v;
-}
-
-extern inline void __outw_p(unsigned short value, unsigned short port)
-{
-__asm__ __volatile__ ("outw %w0,%w1"
- : /* no outputs */
- :"a" (value),"d" (port));
- SLOW_DOWN_IO;
-}
-
-extern inline void __outwc_p(unsigned short value, unsigned short port)
-{
-__asm__ __volatile__ ("outw %w0,%1"
- : /* no outputs */
- :"a" (value),"i" (port));
- SLOW_DOWN_IO;
-}
-
-extern inline unsigned int __inw_p(unsigned short port)
-{
- unsigned int _v;
-__asm__ __volatile__ ("inw %w1,%w0"
- :"=a" (_v):"d" (port),"0" (0));
- SLOW_DOWN_IO;
- return _v;
-}
-
-extern inline unsigned int __inwc_p(unsigned short port)
-{
- unsigned int _v;
-__asm__ __volatile__ ("inw %1,%w0"
- :"=a" (_v):"i" (port),"0" (0));
- SLOW_DOWN_IO;
- return _v;
-}
-
-/*
- * Note that due to the way __builtin_constant_p() works, you
- * - can't use it inside a inlien function (it will never be true)
- * - you don't have to worry about side effects within the __builtin..
- */
-#define outw(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outwc((val),(port)) : \
- __outw((val),(port)))
-
-#define inw(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inwc(port) : \
- __inw(port))
-
-#define outw_p(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outwc_p((val),(port)) : \
- __outw_p((val),(port)))
-
-#define inw_p(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inwc_p(port) : \
- __inw_p(port))
+/* no longer used */
#endif
-
-/* The word-wide I/O operations are more general, but require a halved
- count. */
-#define port_read(port,buf,nr) \
-__asm__("cld;rep;insw": :"d" (port),"D" (buf),"c" (nr):"cx","di")
-#define port_write(port,buf,nr) \
-__asm__("cld;rep;outsw": :"d" (port),"S" (buf),"c" (nr):"cx","si")
-
-#define port_read_b(port,buf,nr) \
-__asm__("cld;rep;insb": :"d" (port),"D" (buf),"c" (nr):"cx","di")
-#define port_write_b(port,buf,nr) \
-__asm__("cld;rep;outsb": :"d" (port),"S" (buf),"c" (nr):"cx","si")
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index b80ecbd..4e9642b 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -14,7 +14,7 @@
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
-static char *version = "lance.c:v0.13s 11/15/93 becker@super.org\n";
+static char *version = "lance.c:v0.14g 12/21/93 becker@super.org\n";
#include <linux/config.h>
#include <linux/kernel.h>
@@ -30,7 +30,6 @@ static char *version = "lance.c:v0.13s 11/15/93 becker@super.org\n";
#include <asm/dma.h>
#include "dev.h"
-#include "iow.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
@@ -145,7 +144,7 @@ tx_full and tbusy flags.
Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). */
#ifndef LANCE_LOG_TX_BUFFERS
-#define LANCE_LOG_TX_BUFFERS 2
+#define LANCE_LOG_TX_BUFFERS 4
#define LANCE_LOG_RX_BUFFERS 4
#endif
@@ -224,7 +223,6 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
{
int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0};
- printk("lance_init(%#x, %#x).\n", mem_start, mem_end);
for (port = &ports[0]; *port; port++) {
int ioaddr = *port;
@@ -336,7 +334,8 @@ static unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
dev->irq = autoirq_report(1);
if (dev->irq)
- printk(", probed IRQ %d, fixed at DMA %d.\n", dev->irq, dev->dma);
+ printk(", probed IRQ %d, fixed at DMA %d.\n",
+ dev->irq, dev->dma);
else {
printk(", failed to detect IRQ line.\n");
return mem_start;
@@ -617,13 +616,6 @@ lance_interrupt(int reg_ptr)
if (csr0 & 0x0200) { /* Tx-done interrupt */
int dirty_tx = lp->dirty_tx;
- if (dirty_tx == lp->cur_tx - TX_RING_SIZE
- && dev->tbusy) {
- /* The ring is full, clear tbusy. */
- dev->tbusy = 0;
- mark_bh(INET_BH);
- }
-
while (dirty_tx < lp->cur_tx) {
int entry = dirty_tx & TX_RING_MOD_MASK;
int status = lp->tx_ring[entry].base;
@@ -650,7 +642,7 @@ lance_interrupt(int reg_ptr)
/* 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
- should always works. */
+ should always work. */
if (databuff >= (void*)(&lp->tx_bounce_buffs[TX_RING_SIZE])
|| databuff < (void*)(lp->tx_bounce_buffs)) {
struct sk_buff *skb = ((struct sk_buff *)databuff) - 1;
@@ -660,15 +652,21 @@ lance_interrupt(int reg_ptr)
dirty_tx++;
}
- lp->dirty_tx = dirty_tx;
-
#ifndef final_version
if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
printk("out-of-sync dirty pointer, %d vs. %d.\n",
dirty_tx, lp->cur_tx);
- lp->dirty_tx += TX_RING_SIZE;
+ dirty_tx += TX_RING_SIZE;
}
#endif
+
+ if (dev->tbusy && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ /* The ring is no longer full, clear tbusy. */
+ dev->tbusy = 0;
+ mark_bh(INET_BH);
+ }
+
+ lp->dirty_tx = dirty_tx;
}
if (csr0 & 0x8000) {
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 0542a82..e198d55 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-14g 12/21/93 Donald Becker (becker@super.org)\n";
+ "ne.c:v0.99-14a 12/3/93 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
@@ -25,9 +25,6 @@ static char *version =
#include <linux/errno.h>
#include <asm/system.h>
#include <asm/io.h>
-#ifndef port_read
-#include "iow.h"
-#endif
#include "dev.h"
#include "8390.h"
@@ -306,11 +303,11 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
if (ei_status.word16) {
- port_read(NE_BASE + NE_DATAPORT,buf,count>>1);
+ insw(NE_BASE + NE_DATAPORT,buf,count>>1);
if (count & 0x01)
buf[count-1] = inb(NE_BASE + NE_DATAPORT), xfer_count++;
} else {
- port_read_b(NE_BASE + NE_DATAPORT, buf, count);
+ insb(NE_BASE + NE_DATAPORT, buf, count);
}
/* This was for the ALPHA version only, but enough people have
@@ -385,9 +382,9 @@ ne_block_output(struct device *dev, int count,
outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
if (ei_status.word16) {
- port_write(NE_BASE + NE_DATAPORT, buf, count>>1);
+ outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
} else {
- port_write_b(NE_BASE + NE_DATAPORT, buf, count);
+ outsb(NE_BASE + NE_DATAPORT, buf, count);
}
/* This was for the ALPHA version only, but enough people have
diff --git a/drivers/net/skeleton.c b/drivers/net/skeleton.c
index 48d64a8..760ca94 100644
--- a/drivers/net/skeleton.c
+++ b/drivers/net/skeleton.c
@@ -57,7 +57,6 @@ static char *version =
#include <errno.h>
#include "dev.h"
-#include "iow.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"
@@ -425,7 +424,7 @@ net_rx(struct device *dev)
memcpy((unsigned char *) (skb + 1), (void*)dev->rmem_start,
pkt_len);
/* or */
- port_read(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
+ insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
#ifdef HAVE_NETIF_RX
netif_rx(skb);
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 17010fb..4939e6f 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -333,17 +333,6 @@ All Rights Reserved\r\n\0 \r\n \r\n", 0x1029, 102
#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
-/* These defines are copied from kernel/blk_drv/hd.c */
-
-#define insw( buf, count, port ) \
- __asm__ volatile \
- ("cld;rep;insw": :"d" (port),"D" (buf),"c" (count):"cx","di" )
-
-#define outsw( buf, count, port ) \
- __asm__ volatile \
- ("cld;rep;outsw": :"d" (port),"S" (buf),"c" (count):"cx","si")
-
-
static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
{
unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
@@ -1469,9 +1458,9 @@ void aha152x_intr( int irqno )
disp_ports();
#endif
- outsw( &current_SC->cmnd,
- COMMAND_SIZE(current_SC->cmnd[0])>>1,
- DATAPORT );
+ outsw( DATAPORT,
+ &current_SC->cmnd,
+ COMMAND_SIZE(current_SC->cmnd[0])>>1 );
#if defined(DEBUG_CMD)
printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() );
@@ -1763,7 +1752,7 @@ void aha152x_intr( int irqno )
{
CLRBITS(DMACNTRL0, _8BIT );
data_count >>= 1; /* Number of words */
- insw( current_SC->SCp.ptr, data_count, DATAPORT );
+ insw( DATAPORT, current_SC->SCp.ptr, data_count );
#if defined(DEBUG_DATAI)
/* show what comes with the last transfer */
if(done)
@@ -1892,7 +1881,7 @@ void aha152x_intr( int irqno )
{
CLRBITS(DMACNTRL0, _8BIT );
data_count >>= 1; /* Number of words */
- outsw( current_SC->SCp.ptr, data_count, DATAPORT );
+ outsw( DATAPORT, current_SC->SCp.ptr, data_count );
current_SC->SCp.ptr += 2 * data_count;
current_SC->SCp.this_residual -= 2 * data_count;
}
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index b82f031..ac41368 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -325,36 +325,6 @@ struct signature {
#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
-/* These functions are based on include/asm/io.h */
-
-inline static unsigned short inw( unsigned short port )
-{
- unsigned short _v;
-
- __asm__ volatile ( "inw %1,%0"
- :"=a" (_v):"d" ((unsigned short) port) );
- return _v;
-}
-
-inline static void outw( unsigned short value, unsigned short port )
-{
- __asm__ volatile ( "outw %0,%1"
- : :"a" ((unsigned short) value),
- "d" ((unsigned short) port) );
-}
-
-
-/* These defines are copied from kernel/blk_drv/hd.c */
-
-#define insw( buf, count, port ) \
- __asm__ volatile \
- ("cld;rep;insw": :"d" (port),"D" (buf),"c" (count):"cx","di" )
-
-#define outsw( buf, count, port ) \
- __asm__ volatile \
- ("cld;rep;outsw": :"d" (port),"S" (buf),"c" (count):"cx","si")
-
-
static void print_banner( void )
{
printk( "%s", fdomain_16x0_info() );
@@ -1113,7 +1083,7 @@ void fdomain_16x0_intr( int unused )
--current_SC->SCp.this_residual;
} else {
data_count >>= 1;
- outsw( current_SC->SCp.ptr, data_count, Write_FIFO_port );
+ outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
current_SC->SCp.ptr += 2 * data_count;
current_SC->SCp.this_residual -= 2 * data_count;
}
@@ -1146,7 +1116,7 @@ void fdomain_16x0_intr( int unused )
--current_SC->SCp.this_residual;
} else {
data_count >>= 1; /* Number of words */
- insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );
+ insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
current_SC->SCp.ptr += 2 * data_count;
current_SC->SCp.this_residual -= 2 * data_count;
}
diff --git a/drivers/sound/sb16_dsp.c b/drivers/sound/sb16_dsp.c
index e8e25cc..f3f18a1 100644
--- a/drivers/sound/sb16_dsp.c
+++ b/drivers/sound/sb16_dsp.c
@@ -220,7 +220,7 @@ sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local)
case SOUND_PCM_WRITE_CHANNELS:
if (local)
return dsp_set_stereo(arg-1)+1;
- return IOCTL_OUT (arg, dsp_set_stereo(IOCTL_IN (arg)-1))+1;
+ return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
case SOUND_PCM_READ_CHANNELS:
if (local)
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 97e2920..bc4b16c 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -25,16 +25,43 @@ void minix_put_inode(struct inode *inode)
minix_free_inode(inode);
}
+static void minix_commit_super (struct super_block * sb,
+ struct minix_super_block * ms)
+{
+ sb->u.minix_sb.s_sbh->b_dirt = 1;
+ sb->s_dirt = 0;
+}
+
+void minix_write_super (struct super_block * sb)
+{
+ struct minix_super_block * ms;
+
+ if (!(sb->s_flags & MS_RDONLY)) {
+ ms = sb->u.minix_sb.s_ms;
+
+ if (ms->s_state & MINIX_VALID_FS)
+ ms->s_state &= ~MINIX_VALID_FS;
+ minix_commit_super (sb, ms);
+ }
+ sb->s_dirt = 0;
+}
+
+
void minix_put_super(struct super_block *sb)
{
int i;
lock_super(sb);
+ if (!(sb->s_flags & MS_RDONLY)) {
+ sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
+ sb->u.minix_sb.s_sbh->b_dirt = 1;
+ }
sb->s_dev = 0;
for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
brelse(sb->u.minix_sb.s_imap[i]);
for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++)
brelse(sb->u.minix_sb.s_zmap[i]);
+ brelse (sb->u.minix_sb.s_sbh);
unlock_super(sb);
return;
}
@@ -45,11 +72,46 @@ static struct super_operations minix_sops = {
minix_write_inode,
minix_put_inode,
minix_put_super,
- NULL,
+ minix_write_super,
minix_statfs,
- NULL
+ minix_remount
};
+int minix_remount (struct super_block * sb, int * flags, char * data)
+{
+ struct minix_super_block * ms;
+
+ ms = sb->u.minix_sb.s_ms;
+ if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ return 0;
+ if (*flags & MS_RDONLY) {
+ if (ms->s_state & MINIX_VALID_FS ||
+ !(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS))
+ return 0;
+ /* Mounting a rw partition read-only. */
+ ms->s_state = sb->u.minix_sb.s_mount_state;
+ sb->u.minix_sb.s_sbh->b_dirt = 1;
+ sb->s_dirt = 1;
+ minix_commit_super (sb, ms);
+ }
+ else {
+ /* Mount a partition which is read-only, read-write. */
+ sb->u.minix_sb.s_mount_state = ms->s_state;
+ ms->s_state &= ~MINIX_VALID_FS;
+ sb->u.minix_sb.s_sbh->b_dirt = 1;
+ sb->s_dirt = 1;
+
+ if (!(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS))
+ printk ("MINIX-fs warning: remounting unchecked fs, "
+ "running fsck is recommended.\n");
+ else if ((sb->u.minix_sb.s_mount_state & MINIX_ERROR_FS))
+ printk ("MINIX-fs warning: remounting fs with errors, "
+ "running fsck is recommended.\n");
+ }
+ return 0;
+}
+
+
struct super_block *minix_read_super(struct super_block *s,void *data,
int silent)
{
@@ -67,6 +129,9 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
return NULL;
}
ms = (struct minix_super_block *) bh->b_data;
+ s->u.minix_sb.s_ms = ms;
+ s->u.minix_sb.s_sbh = bh;
+ s->u.minix_sb.s_mount_state = ms->s_state;
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->u.minix_sb.s_ninodes = ms->s_ninodes;
@@ -77,7 +142,6 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
s->u.minix_sb.s_log_zone_size = ms->s_log_zone_size;
s->u.minix_sb.s_max_size = ms->s_max_size;
s->s_magic = ms->s_magic;
- brelse(bh);
if (s->s_magic == MINIX_SUPER_MAGIC) {
s->u.minix_sb.s_dirsize = 16;
s->u.minix_sb.s_namelen = 14;
@@ -87,9 +151,9 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
} else {
s->s_dev = 0;
unlock_super(s);
+ brelse(bh);
if (!silent)
- printk("VFS: Can't find a minix filesystem on dev 0x%04x.\n",
- dev);
+ printk("VFS: Can't find a minix filesystem on dev 0x%04x.\n", dev);
return NULL;
}
for (i=0;i < MINIX_I_MAP_SLOTS;i++)
@@ -114,21 +178,34 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
brelse(s->u.minix_sb.s_zmap[i]);
s->s_dev=0;
unlock_super(s);
+ brelse(bh);
printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
return NULL;
}
set_bit(0,s->u.minix_sb.s_imap[0]->b_data);
set_bit(0,s->u.minix_sb.s_zmap[0]->b_data);
+ unlock_super(s);
/* set up enough so that it can read an inode */
s->s_dev = dev;
s->s_op = &minix_sops;
s->s_mounted = iget(s,MINIX_ROOT_INO);
- unlock_super(s);
if (!s->s_mounted) {
s->s_dev = 0;
+ brelse(bh);
printk("MINIX-fs: get root inode failed\n");
return NULL;
}
+ if (!(s->s_flags & MS_RDONLY)) {
+ ms->s_state &= ~MINIX_VALID_FS;
+ bh->b_dirt = 1;
+ s->s_dirt = 1;
+ }
+ if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
+ printk ("MINIX-fs: mounting unchecked file system, "
+ "running fsck is recommended.\n");
+ else if (s->u.minix_sb.s_mount_state & MINIX_ERROR_FS)
+ printk ("MINIX-fs: mounting file system with errors, "
+ "running fsck is recommended.\n");
return s;
}
diff --git a/include/asm/io.h b/include/asm/io.h
index b510959..e9ad940 100644
--- a/include/asm/io.h
+++ b/include/asm/io.h
@@ -52,6 +52,16 @@ __IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "i" (port) ,##i ); return _v; } \
__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
__IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "i" (port) ,##i ); SLOW_DOWN_IO; return _v; }
+#define __INS(s) \
+extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("cld ; rep ; ins" #s \
+: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define __OUTS(s) \
+extern inline void outs##s(unsigned short port, void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("cld ; rep ; outs" #s \
+: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
__IN(b,"b","0" (0))
__IN(w,"w","0" (0))
__IN(l,"")
@@ -60,6 +70,14 @@ __OUT(b,"b",char)
__OUT(w,"w",short)
__OUT(l,,int)
+__INS(b)
+__INS(w)
+__INS(l)
+
+__OUTS(b)
+__OUTS(w)
+__OUTS(l)
+
/*
* Note that due to the way __builtin_constant_p() works, you
* - can't use it inside a inline function (it will never be true)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 83e1d82..cac50aa 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -49,6 +49,7 @@ extern unsigned long file_table_init(unsigned long start, unsigned long end);
#define MAJOR(a) (int)((unsigned short)(a) >> 8)
#define MINOR(a) (int)((unsigned short)(a) & 0xFF)
+#define MKDEV(a,b) ((int)((((a) & 0xff) << 8) | ((b) & 0xff)))
#ifndef NULL
#define NULL ((void *) 0)
diff --git a/include/linux/mcd.h b/include/linux/mcd.h
index 45b546d..3dedf80 100644
--- a/include/linux/mcd.h
+++ b/include/linux/mcd.h
@@ -68,7 +68,7 @@
/* borrowed from hd.c */
#define READ_DATA(port, buf, nr) \
-__asm__("cld;rep;insb": :"d" (port),"D" (buf),"c" (nr):"cx","di")
+insb(port, buf, nr)
#define SET_TIMER(func, jifs) \
((timer_table[MCD_TIMER].expires = jiffies + jifs), \
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index ef59ad0..9ddfde7 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -22,6 +22,8 @@
#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
#define NEW_MINIX_SUPER_MAGIC 0x2468 /* minix V2 - not implemented */
+#define MINIX_VALID_FS 0x0001 /* Clean fs. */
+#define MINIX_ERROR_FS 0x0002 /* fs has errors. */
#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
@@ -65,6 +67,7 @@ struct minix_super_block {
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
+ unsigned short s_state;
};
struct minix_dir_entry {
@@ -100,6 +103,8 @@ extern struct buffer_head * minix_bread(struct inode *, int, int);
extern void minix_truncate(struct inode *);
extern void minix_put_super(struct super_block *);
extern struct super_block *minix_read_super(struct super_block *,void *,int);
+extern void minix_write_super(struct super_block *);
+extern int minix_remount (struct super_block * sb, int * flags, char * data);
extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *);
extern void minix_put_inode(struct inode *);
diff --git a/include/linux/minix_fs_sb.h b/include/linux/minix_fs_sb.h
index c6f0625..a483479 100644
--- a/include/linux/minix_fs_sb.h
+++ b/include/linux/minix_fs_sb.h
@@ -16,6 +16,9 @@ struct minix_sb_info {
struct buffer_head * s_zmap[8];
unsigned long s_dirsize;
unsigned long s_namelen;
+ struct buffer_head * s_sbh;
+ struct minix_super_block * s_ms;
+ unsigned short s_mount_state;
};
#endif
diff --git a/kernel/exit.c b/kernel/exit.c
index 0ec3217..41e7742 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -429,7 +429,7 @@ fake_volatile:
current->p_cptr = p->p_osptr;
p->p_ysptr = NULL;
p->flags &= ~(PF_PTRACED|PF_TRACESYS);
- if (task[1])
+ if (task[1] && task[1] != current)
p->p_pptr = task[1];
else
p->p_pptr = task[0];
diff --git a/kernel/ksyms.sh b/kernel/ksyms.sh
index 4a98ab1..d46f091 100644
--- a/kernel/ksyms.sh
+++ b/kernel/ksyms.sh
@@ -10,7 +10,7 @@
#
#
-trap "rm -f ksyms.tmp ksyms.lst" 0 1 2
+trap "rm -f ksyms.tmp ksyms.lst" 1 2
sed -e '/^#/d' -e '/^[ ]*$/d' ksyms.lst | sort > ksyms.tmp
@@ -27,7 +27,7 @@ awk 'BEGIN {stringloc = 0}
echo '
strings:'
awk '{print " .ascii \"" $1 "\\0\""}' ksyms.tmp
-
+rm -f ksyms.tmp
#
diff --git a/kernel/sched.c b/kernel/sched.c
index 17eca1b..17703c7 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -748,8 +748,10 @@ static void show_task(int nr,struct task_struct * p)
printk(stat_nam[p->state]);
else
printk(" ");
- /* this prints bogus values for the current process */
- printk(" %08lX ", ((unsigned long *)p->tss.esp)[2]);
+ if (p == current)
+ printk(" current ");
+ else
+ printk(" %08lX ", ((unsigned long *)p->tss.esp)[3]);
printk("%5lu %5d %6d ",
p->tss.esp - p->kernel_stack_page, p->pid, p->p_pptr->pid);
if (p->p_cptr)
diff --git a/kernel/traps.c b/kernel/traps.c
index 03ddea5..776dff0 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -22,6 +22,12 @@
#include <asm/segment.h>
#include <asm/io.h>
+static inline void console_verbose(void)
+{
+ extern int console_loglevel;
+ console_loglevel = 15;
+}
+
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
@@ -78,6 +84,7 @@ asmlinkage void alignment_check(void);
if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
return;
+ console_verbose();
printk("%s: %04lx\n", str, err & 0xffff);
printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
diff --git a/net/inet/icmp.c b/net/inet/icmp.c
index abd1cb5..31049b9 100644
--- a/net/inet/icmp.c
+++ b/net/inet/icmp.c
@@ -357,7 +357,6 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
unsigned long saddr, int redo, struct inet_protocol *protocol)
{
struct icmphdr *icmph;
- unsigned char *buff;
/* Drop broadcast packets. */
if (chk_addr(daddr) == IS_BROADCAST) {
@@ -368,8 +367,10 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
return(0);
}
- buff = skb1->h.raw;
- icmph = (struct icmphdr *) buff;
+ /* Skip IP-Header */
+ len -= skb1->h.iph->ihl << 2;
+ skb1->h.raw += skb1->h.iph->ihl << 2;
+ icmph = (struct icmphdr *) skb1->h.raw;
/* Validate the packet first */
if (ip_compute_csum((unsigned char *) icmph, len)) {
diff --git a/net/inet/ip.c b/net/inet/ip.c
index 3a1b1fc..5f76d91 100644
--- a/net/inet/ip.c
+++ b/net/inet/ip.c
@@ -428,21 +428,22 @@ ip_fast_csum(unsigned char * buff, int wlen)
{
unsigned long sum = 0;
- if (wlen)
+ if (wlen) {
+ unsigned long bogus;
__asm__("clc\n"
"1:\t"
"lodsl\n\t"
- "adcl %%eax, %0\n\t"
+ "adcl %3, %0\n\t"
"decl %2\n\t"
"jne 1b\n\t"
"adcl $0, %0\n\t"
- "movl %0, %%eax\n\t"
- "shrl $16, %%eax\n\t"
- "addw %%ax, %w0\n\t"
+ "movl %0, %3\n\t"
+ "shrl $16, %3\n\t"
+ "addw %w3, %w0\n\t"
"adcw $0, %w0"
- : "=r" (sum), "=S" (buff), "=r" (wlen)
- : "0" (sum), "1" (buff), "2" (wlen)
- : "ax" );
+ : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus)
+ : "0" (sum), "1" (buff), "2" (wlen));
+ }
return (~sum) & 0xffff;
}
@@ -1266,7 +1267,6 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
}
/* Point into the IP datagram, just past the header. */
- skb->h.raw += iph->ihl*4;
hash = iph->protocol & (MAX_INET_PROTOS -1);
for (ipprot = (struct inet_protocol *)inet_protos[hash];
ipprot != NULL;
@@ -1305,7 +1305,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* check the protocol handler's return values here...
*/
ipprot->handler(skb2, dev, opts_p ? &opt : 0, iph->daddr,
- (ntohs(iph->tot_len) - (iph->ihl * 4)),
+ ntohs(iph->tot_len),
iph->saddr, 0, ipprot);
}
diff --git a/net/inet/route.c b/net/inet/route.c
index c914c7c..09ab097 100644
--- a/net/inet/route.c
+++ b/net/inet/route.c
@@ -44,7 +44,7 @@
static struct rtable *rt_base = NULL;
-
+static struct rtable *rt_loopback = NULL;
/* Dump the contents of a routing table entry. */
static void
@@ -80,6 +80,8 @@ static void rt_del(unsigned long dst)
continue;
}
*rp = r->rt_next;
+ if (rt_loopback == r)
+ rt_loopback = NULL;
kfree_s(r, sizeof(struct rtable));
}
restore_flags(flags);
@@ -105,6 +107,8 @@ void rt_flush(struct device *dev)
continue;
}
*rp = r->rt_next;
+ if (rt_loopback == r)
+ rt_loopback = NULL;
kfree_s(r, sizeof(struct rtable));
}
restore_flags(flags);
@@ -216,6 +220,8 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
continue;
}
*rp = r->rt_next;
+ if (rt_loopback == r)
+ rt_loopback = NULL;
kfree_s(r, sizeof(struct rtable));
}
/* add the new route */
@@ -227,6 +233,8 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
}
rt->rt_next = r;
*rp = rt;
+ if (rt->rt_dev->flags & IFF_LOOPBACK)
+ rt_loopback = rt;
restore_flags(cpuflags);
return;
}
@@ -306,41 +314,28 @@ rt_get_info(char *buffer)
return(pos - buffer);
}
-
/*
- * rewrote this too.. Maybe somebody can understand it now. Linus
+ * This is hackish, but results in better code. Use "-S" to see why.
*/
+#define early_out ({ goto no_route; 1; })
+
struct rtable * rt_route(unsigned long daddr, struct options *opt)
{
struct rtable *rt;
- int type;
- /*
- * This is a hack, I think. -FvK
- */
- if ((type=chk_addr(daddr)) == IS_MYADDR) daddr = my_addr();
-
- /*
- * Loop over the IP routing table to find a route suitable
- * for this packet. Note that we really should have a look
- * at the IP options to see if we have been given a hint as
- * to what kind of path we should use... -FvK
- */
- /*
- * This depends on 'rt_mask' and the ordering set up in 'rt_add()' - Linus
- */
- for (rt = rt_base; rt != NULL; rt = rt->rt_next) {
- if (!((rt->rt_dst ^ daddr) & rt->rt_mask)) {
- rt->rt_use++;
- return rt;
- }
+ for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) {
+ if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
+ break;
/* broadcast addresses can be special cases.. */
if ((rt->rt_dev->flags & IFF_BROADCAST) &&
- rt->rt_dev->pa_brdaddr == daddr) {
- rt->rt_use++;
- return(rt);
- }
+ rt->rt_dev->pa_brdaddr == daddr)
+ break;
}
+ if (daddr == rt->rt_dev->pa_addr)
+ rt = rt_loopback;
+ rt->rt_use++;
+ return rt;
+no_route:
return NULL;
}
diff --git a/net/inet/tcp.c b/net/inet/tcp.c
index 83dfb41..c3be0bc 100644
--- a/net/inet/tcp.c
+++ b/net/inet/tcp.c
@@ -2934,6 +2934,9 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
DPRINTF((DBG_TCP, "tcp.c: tcp_rcv dev = NULL\n"));
return(0);
}
+ /* Skip IP-Header */
+ len -= skb->h.iph->ihl << 2;
+ skb->h.raw += skb->h.iph->ihl << 2;
th = skb->h.th;
/* Find the socket. */
diff --git a/net/inet/udp.c b/net/inet/udp.c
index 78066c3..74e0a2e 100644
--- a/net/inet/udp.c
+++ b/net/inet/udp.c
@@ -550,6 +550,9 @@ udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
struct sock *sk;
struct udphdr *uh;
+ /* Skip IP-Header */
+ len -= skb->h.iph->ihl << 2;
+ skb->h.raw += skb->h.iph->ihl << 2;
uh = (struct udphdr *) skb->h.uh;
sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
if (sk == NULL)
diff --git a/net/socket.c b/net/socket.c
index 6885fe7..e679128 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -231,6 +231,7 @@ static void
sock_release(struct socket *sock)
{
int oldstate;
+ struct inode *inode;
struct socket *peersock, *nextsock;
DPRINTF((net_debug, "NET: sock_release: socket 0x%x, inode 0x%x\n",
@@ -251,11 +252,12 @@ sock_release(struct socket *sock)
peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL;
if (sock->ops) sock->ops->release(sock, peersock);
if (peersock) sock_release_peer(peersock);
+ inode = SOCK_INODE(sock);
sock->state = SS_FREE; /* this really releases us */
wake_up(&socket_wait_free);
/* We need to do this. If sock alloc was called we already have an inode. */
- iput(SOCK_INODE(sock));
+ iput(inode);
}
diff --git a/net/unix/proc.c b/net/unix/proc.c
index 68bd106..8a80ad5 100644
--- a/net/unix/proc.c
+++ b/net/unix/proc.c
@@ -16,7 +16,6 @@
* Fred Baumgarten, <dc6iq@insu1.etec.uni-kalrsruhe.de>
*
* Fixes:
- * Andriews Brouwer : Comment errors
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License