Commit 6e38a55b authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.53

parent 5f50b72d
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 52
SUBLEVEL = 53
ARCH = i386
......@@ -136,7 +136,11 @@ tools/version.h: $(CONFIGURE) Makefile
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
@echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\" >> tools/version.h
@if [ -x /bin/dnsdomainname ]; then \
echo \#define LINUX_COMPILE_DOMAIN \"`dnsdomainname`\"; \
else \
echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\"; \
fi >> tools/version.h
@echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> tools/version.h
tools/build: tools/build.c $(CONFIGURE)
......
......@@ -1081,20 +1081,32 @@ static void reset_terminal(int currcons, int do_clear)
}
/*
* Turn the Scroll-Lock LED on when the tty is stopped (with a ^S)
* Turn the Scroll-Lock LED on when the tty is stopped
*/
static void con_stop(struct tty_struct *tty)
{
set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
int console_num;
if (!tty)
return;
console_num = MINOR(tty->device) - (tty->driver.minor_start);
if (console_num < 0 || console_num >= NR_CONSOLES)
return;
set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
set_leds();
}
/*
* Turn the Scroll-Lock LED off when the console is started (with a ^Q)
* Turn the Scroll-Lock LED off when the console is started
*/
static void con_start(struct tty_struct *tty)
{
clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
int console_num;
if (!tty)
return;
console_num = MINOR(tty->device) - (tty->driver.minor_start);
if (console_num < 0 || console_num >= NR_CONSOLES)
return;
clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
set_leds();
}
......
This diff is collapsed.
/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
/*
Written 1992,1993 by Donald Becker.
Written 1992-94 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.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This driver should work with the 3c503 and 3c503/16. It should be used
in shared memory mode for best performance, although it may also work
in programmed-I/O mode.
The Author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Sources:
EtherLink II Technical Reference Guide,
3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
The Crynwr 3c503 packet driver.
*/
static char *version =
"3c503.c:v0.99.15k 3/3/93 Donald Becker (becker@super.org)\n";
"3c503.c:v1.10 9/23/93 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -31,9 +38,27 @@ static char *version =
#include "8390.h"
#include "3c503.h"
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
int el2_probe(struct device *dev);
int el2_pio_autoprobe(struct device *dev);
int el2probe1(int ioaddr, struct device *dev);
int el2_pio_probe(struct device *dev);
int el2_probe1(struct device *dev, int ioaddr);
/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
static unsigned int netcard_portlist[] =
{ 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
#define EL2_IO_EXTENT 16
#ifdef HAVE_DEVLIST
/* The 3c503 uses two entries, one for the safe memory-mapped probe and
the other for the typical I/O probe. */
struct netdev_entry el2_drv =
{"3c503", el2_probe, EL1_IO_EXTENT, 0};
struct netdev_entry el2pio_drv =
{"3c503pio", el2_pioprobe1, EL1_IO_EXTENT, netcard_portlist};
#endif
static int el2_open(struct device *dev);
static int el2_close(struct device *dev);
......@@ -52,19 +77,16 @@ static int el2_block_input(struct device *dev, int count, char *buf,
If the ethercard isn't found there is an optional probe for
ethercard jumpered to programmed-I/O mode.
*/
static int ports[] = {0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
int
el2_probe(struct device *dev)
{
int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
short ioaddr = dev->base_addr;
int base_addr = dev->base_addr;
if (ioaddr < 0)
return ENXIO; /* Don't probe at all. */
if (ioaddr > 0)
return ! el2probe1(ioaddr, dev);
if (base_addr > 0x1ff) /* Check a single specified location. */
return el2_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (addr = addrs; *addr; addr++) {
int i;
......@@ -75,86 +97,99 @@ el2_probe(struct device *dev)
break;
if (base_bits != 1)
continue;
#ifdef HAVE_PORTRESERVE
if (check_region(ports[i], 16))
if (check_region(netcard_portlist[i], EL2_IO_EXTENT))
continue;
#endif
if (el2probe1(ports[i], dev))
if (el2_probe1(dev, netcard_portlist[i]) == 0)
return 0;
}
#ifndef no_probe_nonshared_memory
return el2_pio_autoprobe(dev);
#if ! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST)
return el2_pio_probe(dev);
#else
return ENODEV;
#endif
}
#ifndef HAVE_DEVLIST
/* Try all of the locations that aren't obviously empty. This touches
a lot of locations, and is much riskier than the code above. */
int
el2_pio_autoprobe(struct device *dev)
el2_pio_probe(struct device *dev)
{
int i;
for (i = 0; i < 8; i++) {
#ifdef HAVE_PORTRESERVE
if (check_region(ports[i], 16))
continue;
#endif
/* Reset and/or avoid any lurking NE2000 */
if (inb_p(ports[i] + 0x408) == 0xff)
int base_addr = dev ? dev->base_addr : 0;
if (base_addr > 0x1ff) /* Check a single specified location. */
return el2_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (i = 0; netcard_portlist[i]; i++) {
int ioaddr = netcard_portlist[i];
if (check_region(ioaddr, EL2_IO_EXTENT))
continue;
if (inb(ports[i] + 0x403) == (0x80 >> i) /* Preliminary check */
&& el2probe1(ports[i], dev))
if (el2_probe1(dev, ioaddr) == 0)
return 0;
}
return ENODEV;
}
#endif
/* Probe for the Etherlink II card at I/O port base IOADDR,
returning non-zero on success. If found, set the station
address and memory parameters in DEVICE. */
int
el2probe1(int ioaddr, struct device *dev)
el2_probe1(struct device *dev, int ioaddr)
{
int i, iobase_reg, membase_reg, saved_406;
unsigned char *station_addr = dev->dev_addr;
static unsigned version_printed = 0;
/* Reset and/or avoid any lurking NE2000 */
if (inb(ioaddr + 0x408) == 0xff)
return ENODEV;
/* We verify that it's a 3C503 board by checking the first three octets
of its ethernet address. */
printk("3c503 probe at %#3x:", ioaddr);
iobase_reg = inb(ioaddr+0x403);
membase_reg = inb(ioaddr+0x404);
/* Verify ASIC register that should be 0 or have a single bit set. */
/* ASIC location registers should be 0 or have only a single bit set. */
if ( (iobase_reg & (iobase_reg - 1))
|| (membase_reg & (membase_reg - 1))) {
printk(" not found.\n");
return 0;
return ENODEV;
}
saved_406 = inb_p(ioaddr + 0x406);
outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
outb_p(ECNTRL_THIN, ioaddr + 0x406);
/* Map the station addr PROM into the lower I/O ports. */
outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
for (i = 0; i < ETHER_ADDR_LEN; i++) {
printk(" %2.2X", (station_addr[i] = inb(ioaddr + i)));
}
if ( station_addr[0] != 0x02
|| station_addr[1] != 0x60
|| station_addr[2] != 0x8c) {
printk(" 3C503 not found.\n");
if ( inb(ioaddr + 0) != 0x02
|| inb(ioaddr + 1) != 0x60
|| inb(ioaddr + 2) != 0x8c) {
/* Restore the register we frobbed. */
outb(saved_406, ioaddr + 0x406);
return 0;
return ENODEV;
}
#ifdef HAVE_PORTRESERVE
snarf_region(ioaddr, 16);
#endif
snarf_region(ioaddr, EL2_IO_EXTENT);
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
if (ei_debug && version_printed++ == 0)
printk(version);
dev->base_addr = ioaddr;
ethdev_init(dev);
printk("%s: 3c503 at %#3x,", dev->name, ioaddr);
/* Retrive and print the ethernet address. */
for (i = 0; i < 6; i++)
printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
/* Map the 8390 back into the window. */
outb(ECNTRL_THIN, ioaddr + 0x406);
dev->base_addr = ioaddr;
/* Probe for, turn on and clear the board's shared memory. */
if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg);
outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */
......@@ -231,10 +266,11 @@ el2probe1(int ioaddr, struct device *dev)
else
printk("\n%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).\n",
dev->name, ei_status.name);
if (ei_debug > 1)
printk(version);
return ioaddr;
return 0;
}
static int
......@@ -425,5 +461,6 @@ el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
* Local variables:
* version-control: t
* kept-new-versions: 5
* c-indent-level: 4
* End:
*/
/* 3c507.c: An EtherLink16 device 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,
incorporated herein by reference.
Written 1993,1994 by Donald Becker.
The author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
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.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
......@@ -21,7 +24,7 @@
*/
static char *version =
"3c507.c:v0.99-15f 2/17/94 Donald Becker (becker@super.org)\n";
"3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
......@@ -33,7 +36,7 @@ static char *version =
for Russ Nelson.
Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough
info that the casual reader might think that it documents the i82586.
info that the casual reader might think that it documents the i82586 :-<.
*/
#include <linux/kernel.h>
......@@ -56,12 +59,20 @@ static char *version =
#include <linux/skbuff.h>
#include <linux/malloc.h>
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
/* use 0 for production, 1 for verification, 2..7 for debug */
#ifndef NET_DEBUG
#define NET_DEBUG 1
#endif
static unsigned int net_debug = NET_DEBUG;
/* A zero-terminated list of common I/O addresses to be probed. */
static unsigned int netcard_portlist[] =
{ 0x300, 0x320, 0x340, 0x280, 0};
/*
Details of the i82586.
......@@ -130,6 +141,7 @@ struct net_local {
#define ROM_CONFIG 13
#define MEM_CONFIG 14
#define IRQ_CONFIG 15
#define EL16_IO_EXTENT 16
/* The ID port is used at boot-time to locate the ethercard. */
#define ID_PORT 0x100
......@@ -267,7 +279,7 @@ unsigned short init_words[] = {
extern int el16_probe(struct device *dev); /* Called from Space.c */
static int el16_probe1(struct device *dev, short ioaddr);
static int el16_probe1(struct device *dev, int ioaddr);
static int el16_open(struct device *dev);
static int el16_send_packet(struct sk_buff *skb, struct device *dev);
static void el16_interrupt(int reg_ptr);
......@@ -279,6 +291,11 @@ static void hardware_send_packet(struct device *dev, void *buf, short length);
void init_82586_mem(struct device *dev);
#ifdef HAVE_DEVLIST
struct netdev_entry netcard_drv =
{"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist};
#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.
......@@ -288,17 +305,33 @@ void init_82586_mem(struct device *dev);
int
el16_probe(struct device *dev)
{
/* Don't probe all settable addresses, 0x[23][0-F]0, just common ones. */
int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0};
int base_addr = dev->base_addr;
ushort lrs_state = 0xff, i;
int base_addr = dev ? dev->base_addr : 0;
int i;
if (base_addr > 0x1ff) /* Check a single specified location. */
return el16_probe1(dev, base_addr);
else if (base_addr > 0)
else if (base_addr != 0)
return ENXIO; /* Don't probe at all. */
/* Send the ID sequence to the ID_PORT to enable the board. */
for (i = 0; netcard_portlist[i]; i++) {
int ioaddr = netcard_portlist[i];
if (check_region(ioaddr, EL16_IO_EXTENT))
continue;
if (el16_probe1(dev, ioaddr) == 0)
return 0;
}
return ENODEV; /* ENODEV would be more accurate. */
}
int el16_probe1(struct device *dev, int ioaddr)
{
static unsigned char init_ID_done = 0, version_printed = 0;
int i, irq, irqval;
if (init_ID_done == 0) {
ushort lrs_state = 0xff;
/* Send the ID sequence to the ID_PORT to enable the board(s). */
outb(0x00, ID_PORT);
for(i = 0; i < 255; i++) {
outb(lrs_state, ID_PORT);
......@@ -307,35 +340,21 @@ el16_probe(struct device *dev)
lrs_state ^= 0xe7;
}
outb(0x00, ID_PORT);
init_ID_done = 1;
}
for (port = &ports[0]; *port; port++) {
short ioaddr = *port;
#if 0
/* This is my original code. */
if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
&& inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O'
&& el16_probe1(dev, *port) == 0)
return 0;
#else
/* This is code from jennings@Montrouge.SMR.slb.com, done so that
the string can be printed out. */
char res[5];
res[0] = inb(ioaddr); res[1] = inb(ioaddr+1);
res[2] = inb(ioaddr+2); res[3] = inb(ioaddr+3);
res[4] = 0;
if (res[0] == '*' && res[1] == '3'
&& res[2] == 'C' && res[3] == 'O'
&& el16_probe1(dev, *port) == 0)
return 0;
#endif
}
&& inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O')
;
else
return ENODEV;
return ENODEV; /* ENODEV would be more accurate. */
}
/* Allocate a new 'dev' if needed. */
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct net_local), 0);
int el16_probe1(struct device *dev, short ioaddr)
{
int i, irq, irqval;
if (net_debug && version_printed++ == 0)
printk(version);
printk("%s: 3c507 at %#x,", dev->name, ioaddr);
......@@ -351,7 +370,7 @@ int el16_probe1(struct device *dev, short ioaddr)
}
/* We've committed to using the board, and can start filling in *dev. */
snarf_region(ioaddr, 16);
snarf_region(ioaddr, EL16_IO_EXTENT);
dev->base_addr = ioaddr;
outb(0x01, ioaddr + MISC_CTRL);
......@@ -394,6 +413,7 @@ int el16_probe1(struct device *dev, short ioaddr)
printk(version);
/* Initialize the device structure. */
if (dev->priv == NULL)
dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct net_local));
......
This diff is collapsed.
/* 8390.c: A general NS8390 ethernet driver core for linux. */
/*
Written 1992,1993 by Donald Becker.
Written 1992-94 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.
Director, National Security Agency.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is the chip-specific code for many 8390-based ethernet adaptors.
This is not a complete driver, it must be combined with board-specific
code such as ne.c, wd.c, 3c503.c, etc.
The Author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
*/
static char *version =
"8390.c:v0.99-15e 2/16/94 Donald Becker (becker@super.org)\n";
"8390.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
/*
Braindamage remaining:
Much of this code should be cleaned up post-1.00, but it has been
extensively beta tested in the current form.
Much of this code should have been cleaned up, but every attempt
has broken some clone part.
Sources:
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
The NE* programming info came from the Crynwr packet driver, and figuring
out that the those boards are similar to the NatSemi evaluation board
described in AN-729. Thanks NS, no thanks to Novell/Eagle.
*/
#include <linux/config.h>
......@@ -302,6 +301,10 @@ void ei_interrupt(int reg_ptr)
}
if (interrupts && ei_debug) {
if (boguscount == 9)
printk("%s: Too much work at interrupt, status %#2.2x\n",
dev->name, interrupts);
else
printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
......
......@@ -41,12 +41,12 @@ struct ei_device {
void (*reset_8390)(struct device *);
void (*block_output)(struct device *, int, const unsigned char *, int);
int (*block_input)(struct device *, int, char *, int);
int open:1;
int word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
int txing:1; /* Transmit Active */
int dmaing:2; /* Remote DMA Active */
int irqlock:1; /* 8390's intrs disabled when '1'. */
int pingpong:1; /* Using the ping-pong driver */
unsigned open:1;
unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
unsigned txing:1; /* Transmit Active */
unsigned dmaing:2; /* Remote DMA Active */
unsigned irqlock:1; /* 8390's intrs disabled when '1'. */
unsigned pingpong:1; /* Using the ping-pong driver */
unsigned char tx_start_page, rx_start_page, stop_page;
unsigned char current_page; /* Read pointer in buffer */
unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
......
/* at1700.c: A network device driver for the Allied Telesis AT1700.
Written 1993 by Donald Becker. This is a alpha test limited release.
This version may only be used and distributed according to the terms of the
GNU Public License, incorporated herein by reference.
Written 1993-94 by Donald Becker.
The author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
This is a device driver for the Allied Telesis AT1700, which is a
straightforward Fujitsu MB86965 implementation.
*/
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
static char *version =
"at1700.c:v0.06 3/3/94 Donald Becker (becker@super.org)\n";
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
#include <linux/config.h>
This is a device driver for the Allied Telesis AT1700, which is a
straight-forward Fujitsu MB86965 implementation.
/*
Sources:
The Fujitsu MB86695 datasheet.
After this driver was written, ATI provided their EEPROM configuration
code header file. Thanks to Gerry Sockins of ATI.
After the initial version of this driver was written Gerry Sockins of
ATI provided their EEPROM configurationcode header file.
Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
Bugs:
The MB86695 has a design flaw that makes all probes unreliable. Not
only is it difficult to detect, it also moves around in I/O space in
response to inb()s from other device probes!
*/
static char *version =
"at1700.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
......@@ -43,19 +52,16 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
#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
/* This unusual address order is used to verify the CONFIG register. */
static int at1700_probe_list[] =
{0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0};
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
#define NET_DEBUG 2
#define NET_DEBUG 1
#endif
static unsigned int net_debug = NET_DEBUG;
......@@ -87,6 +93,9 @@ struct net_local {
#define MODE13 13
#define EEPROM_Ctrl 16
#define EEPROM_Data 17
#define IOCONFIG 19
#define RESET 31 /* Write to reset some parts of the chip. */
#define AT1700_IO_EXTENT 32
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x40 /* EEPROM shift clock, in reg. 16. */
......@@ -124,20 +133,26 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
#ifdef HAVE_DEVLIST
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
struct netdev_entry at1700_drv =
{"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list};
#else
int
at1700_probe(struct device *dev)
{
short ports[] = {0x300, 0x280, 0x380, 0x320, 0x340, 0x260, 0x2a0, 0x240, 0};
short *port, base_addr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (base_addr > 0x1ff) /* Check a single specified location. */
return at1700_probe1(dev, base_addr);
else if (base_addr > 0) /* Don't probe at all. */
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
int ioaddr = *port;
if (check_region(ioaddr, 32))
for (i = 0; at1700_probe_list[i]; i++) {
int ioaddr = at1700_probe_list[i];
if (check_region(ioaddr, AT1700_IO_EXTENT))
continue;
if (at1700_probe1(dev, ioaddr) == 0)
return 0;
......@@ -145,6 +160,7 @@ at1700_probe(struct device *dev)
return ENODEV;
}
#endif
/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
"signature", the default bit pattern after a reset. This *doesn't* work --
......@@ -156,29 +172,24 @@ at1700_probe(struct device *dev)
int at1700_probe1(struct device *dev, short ioaddr)
{
unsigned short signature[4] = {0xffff, 0xffff, 0x7ff7, 0xff5f};
unsigned short signature_invalid[4] = {0xffff, 0xffff, 0x7ff7, 0xdf0f};
char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
unsigned short *station_address = (unsigned short *)dev->dev_addr;
unsigned int i, irq;
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
That means we have to be careful with the register values we probe for.
*/
for (i = 0; i < 4; i++)
if ((inw(ioaddr + 2*i) | signature_invalid[i]) != signature[i]) {
if (net_debug > 2)
printk("AT1700 signature match failed at %d (%04x vs. %04x)\n",
i, inw(ioaddr + 2*i), signature[i]);
return -ENODEV;
}
if (read_eeprom(ioaddr, 4) != 0x0000
|| read_eeprom(ioaddr, 5) & 0x00ff != 0x00F4)
#ifdef notdef
printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
#endif
if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr
|| read_eeprom(ioaddr, 4) != 0x0000
|| read_eeprom(ioaddr, 5) & 0xff00 != 0xF400)
return -ENODEV;
/* Grab the region so that we can find another board if the IRQ request
fails. */
snarf_region(ioaddr, 32);
/* Reset the internal state machines. */
outb(0, ioaddr + RESET);
irq = irqmap[(read_eeprom(ioaddr, 12)&0x04)
| (read_eeprom(ioaddr, 0)>>14)];
......@@ -190,6 +201,14 @@ int at1700_probe1(struct device *dev, short ioaddr)
return EAGAIN;
}
/* Allocate a new 'dev' if needed. */
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct net_local), 0);
/* Grab the region so that we can find another board if the IRQ request
fails. */
snarf_region(ioaddr, AT1700_IO_EXTENT);
printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
ioaddr, irq);
......@@ -200,7 +219,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
for(i = 0; i < 3; i++) {
unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
printk("%04x", eeprom_val);
station_address[i] = ntohs(eeprom_val);
((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
}
/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
......@@ -214,8 +233,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
ushort setup_value = read_eeprom(ioaddr, 12);
dev->if_port = setup_value >> 8;
printk(" %s interface (%04x).\n", porttype[(dev->if_port>>3) & 3],
setup_value);
printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
}
/* Set the station address in bank zero. */
......@@ -243,6 +261,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
printk(version);
/* Initialize the device structure. */
if (dev->priv == NULL)
dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct net_local));
......@@ -252,7 +271,7 @@ int at1700_probe1(struct device *dev, short ioaddr)
dev->get_stats = net_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* Fill in the fields of the device structure with ethernet-generic values. */
/* Fill in the fields of 'dev' with ethernet-generic values. */
ether_setup(dev);
return 0;
......@@ -400,7 +419,9 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
lp->tx_started = 1;
} else if (lp->tx_queue_len < 4096 - 1502) /* Room for one more packet? */
dev->tbusy = 0;
} else if (lp->tx_queue_len < 4096 - 1502)
/* Yes, there is room for one more packet. */
dev->tbusy = 0;
/* Turn on Tx interrupts back on. */
......@@ -453,10 +474,12 @@ net_interrupt(int reg_ptr)
/* Turn on Tx interrupts off. */
outb(0x00, ioaddr + TX_INTR);
dev->tbusy = 0;
mark_bh(NET_BH); /* Inform upper layers. */
}
}
}
dev->interrupt = 0;
return;
}
......@@ -499,7 +522,7 @@ net_rx(struct device *dev)
lp->stats.rx_errors++;
break;
}
skb = alloc_skb(pkt_len, GFP_ATOMIC);
skb = alloc_skb(pkt_len+1, GFP_ATOMIC);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet (len %d).\n",
dev->name, pkt_len);
......@@ -535,6 +558,7 @@ net_rx(struct device *dev)
for (i = 0; i < 20; i++) {
if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
break;
inw(ioaddr + DATAPORT); /* dummy status read */
outb(0x05, ioaddr + 14);
}
......@@ -592,9 +616,9 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
{
short ioaddr = dev->base_addr;
if (num_addrs) {
outw(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
} else
outw(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */
outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */
}
/*
......@@ -603,5 +627,6 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
* version-control: t
* kept-new-versions: 5
* tab-width: 4
* c-indent-level: 4
* End:
*/
/* auto_irq.c: Auto-configure IRQ lines for linux. */
/*
Written 1993 by Donald Becker.
Written 1994 by Donald Becker.
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@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This code is a general-purpose IRQ line detector for devices with
jumpered IRQ lines. If you can make the device raise an IRQ (and
......@@ -12,7 +13,7 @@
device probes!
To use this, first call autoirq_setup(timeout). TIMEOUT is how many
'jiffies' (1/18 sec.) to detect other devices that have active IRQ lines,
'jiffies' (1/100 sec.) to detect other devices that have active IRQ lines,
and can usually be zero at boot. 'autoirq_setup()' returns the bit
vector of nominally-available IRQ lines (lines may be physically in-use,
but not yet registered to a device).
......@@ -27,23 +28,26 @@
#ifdef version
static char *version="auto_irq.c:v0.02 1993 Donald Becker (becker@super.org)";
static char *version=
"auto_irq.c:v1.11 Donald Becker (becker@cesdis.gsfc.nasa.gov)";
#endif
/*#include <linux/config.h>*/
/*#include <linux/kernel.h>*/
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/netdevice.h>
/*#include <asm/system.h>*/
struct device *irq2dev_map[16] = {0, 0, /* ... zeroed */};
int irqs_busy = 0x01; /* The set of fixed IRQs always enabled */
int irqs_used = 0x01; /* The set of fixed IRQs sometimes enabled. */
int irqs_reserved = 0x00; /* An advisory "reserved" table. */
int irqs_shared = 0x00; /* IRQ lines "shared" among conforming cards.*/
int irqs_busy = 0x2147; /* The set of fixed IRQs (keyboard, timer, etc) */
int irqs_used = 0x0001; /* The set of fixed IRQs sometimes enabled. */
int irqs_reserved = 0x0000; /* An advisory "reserved" table. */
int irqs_shared = 0x0000; /* IRQ lines "shared" among conforming cards.*/
static volatile int irq_number; /* The latest irq number we actually found. */
static volatile int irq_bitmap; /* The irqs we actually found. */
......@@ -53,17 +57,20 @@ static void autoirq_probe(int irq)
{
irq_number = irq;
set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */
disable_irq(irq);
return;
}
int autoirq_setup(int waittime)
{
int i, mask;
int timeout = jiffies+waittime;
int timeout = jiffies + waittime;
int boguscount = (waittime*loops_per_sec) / 100;
irq_handled = 0;
for (i = 0; i < 16; i++) {
if (!request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe"))
if (test_bit(i, &irqs_busy) == 0
&& request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe") == 0)
set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/
}
/* Update our USED lists. */
......@@ -72,7 +79,7 @@ int autoirq_setup(int waittime)
irq_bitmap = 0;
/* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
while (timeout > jiffies)
while (timeout > jiffies && --boguscount > 0)
;
for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) {
......@@ -91,9 +98,11 @@ int autoirq_report(int waittime)
{
int i;
int timeout = jiffies+waittime;
int boguscount = (waittime*loops_per_sec) / 100;
/* Hang out at least <waittime> jiffies waiting for the IRQ. */
while (timeout > jiffies)
while (timeout > jiffies && --boguscount > 0)
if (irq_number)
break;
......@@ -110,5 +119,7 @@ int autoirq_report(int waittime)
* compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c"
* version-control: t
* kept-new-versions: 5
* c-indent-level: 4
* tab-width: 4
* End:
*/
......@@ -19,7 +19,7 @@
*/
static char *version =
"hp-plus.c:v0.04 6/16/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/string.h> /* Important -- this inlines word moves. */
......@@ -38,6 +38,12 @@ static char *version =
#endif
#include "8390.h"
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int hpplus_portlist[] =
{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}
/*
The HP EtherTwist chip implementation is a fairly routine DP8390
......@@ -64,10 +70,6 @@ static char *version =
register.
*/
#define HPP_PROBE_LIST {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}
#define HP_IO_EXTENT 32
#define HP_ID 0x00 /* ID register, always 0x4850. */
#define HP_PAGING 0x02 /* Registers visible @ 8-f, see PageName. */
#define HPP_OPTION 0x04 /* Bitmapped options, see HP_Option. */
......@@ -75,6 +77,7 @@ static char *version =
#define HPP_IN_ADDR 0x0A /* I/O input location in Perf_Page. */
#define HP_DATAPORT 0x0c /* I/O data transfer in Perf_Page. */
#define NIC_OFFSET 0x10 /* Offset to the 8390 registers. */
#define HP_IO_EXTENT 32
#define HP_START_PG 0x00 /* First page of TX buffer */
#define HP_STOP_PG 0x80 /* Last page +1 of RX ring */
......@@ -111,26 +114,34 @@ static void hpp_io_block_output(struct device *dev, int count,
/* Probe a list of addresses for an HP LAN+ adaptor.
This routine is almost boilerplate. */
#ifdef HAVE_DEVLIST
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
struct netdev_entry hpplus_drv =
{"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
#else
int hp_plus_probe(struct device *dev)
{
int *port, ports[] = HPP_PROBE_LIST;
short ioaddr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (ioaddr > 0x1ff) /* Check a single specified location. */
return hpp_probe1(dev, ioaddr);
else if (ioaddr > 0) /* Don't probe at all. */
if (base_addr > 0x1ff) /* Check a single specified location. */
return hpp_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
if (check_region(*port, HP_IO_EXTENT))
for (i = 0; hpplus_portlist[i]; i++) {
int ioaddr = hpplus_portlist[i];
if (check_region(ioaddr, HP_IO_EXTENT))
continue;
if (hpp_probe1(dev, *port) == 0) {
if (hpp_probe1(dev, ioaddr) == 0)
return 0;
}
}
return ENODEV;
}
#endif
/* Do the interesting part of the probe at a single address. */
int hpp_probe1(struct device *dev, int ioaddr)
......@@ -138,7 +149,6 @@ int hpp_probe1(struct device *dev, int ioaddr)
int i;
unsigned char checksum = 0;
char *name = "HP-PC-LAN+";
unsigned char *station_addr = dev->dev_addr;
int mem_start;
/* Check for the HP+ signature, 50 48 0x 53. */
......@@ -146,7 +156,9 @@ int hpp_probe1(struct device *dev, int ioaddr)
|| (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300)
return ENODEV;
/* OK, we think that we have it. Get and checksum the physical address. */
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
printk("%s: %s at %#3x,", dev->name, name, ioaddr);
/* Retrieve and checksum the station address. */
......@@ -154,7 +166,7 @@ int hpp_probe1(struct device *dev, int ioaddr)
for(i = 0; i < ETHER_ADDR_LEN; i++) {
unsigned char inval = inb(ioaddr + 8 + i);
station_addr[i] = inval;
dev->dev_addr[i] = inval;
checksum += inval;
printk(" %2.2x", inval);
}
......
/* hp.c: A HP LAN ethernet driver for linux. */
/*
Written 1993 by Donald Becker.
Written 1993-94 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.
Director, National Security Agency.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is a driver for the HP LAN adaptors.
This is a driver for the HP PC-LAN adaptors.
The Author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
Sources:
The Crynwr packet driver.
*/
static char *version =
"hp.c:v0.99.15k 3/3/94 Donald Becker (becker@super.org)\n";
"hp.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -26,10 +32,12 @@ static char *version =
#include <linux/netdevice.h>
#include "8390.h"
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size); do ; while (0)
#endif
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int hppclan_portlist[] =
{ 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
#define HP_IO_EXTENT 32
......@@ -46,7 +54,7 @@ static char *version =
#define HP_16BSTOP_PG 0xFF /* Same, for 16 bit cards. */
int hp_probe(struct device *dev);
int hpprobe1(struct device *dev, int ioaddr);
int hp_probe1(struct device *dev, int ioaddr);
static void hp_reset_8390(struct device *dev);
static int hp_block_input(struct device *dev, int count,
......@@ -63,32 +71,37 @@ 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. */
#ifdef HAVE_DEVLIST
struct netdev_entry netcard_drv =
{"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist};
#else
int hp_probe(struct device *dev)
{
int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
short ioaddr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (ioaddr > 0x1ff) /* Check a single specified location. */
return hpprobe1(dev, ioaddr);
else if (ioaddr > 0) /* Don't probe at all. */
if (base_addr > 0x1ff) /* Check a single specified location. */
return hp_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
if (check_region(*port, HP_IO_EXTENT))
for (i = 0; hppclan_portlist[i]; i++) {
int ioaddr = hppclan_portlist[i];
if (check_region(ioaddr, HP_IO_EXTENT))
continue;
if (hpprobe1(dev, *port) == 0) {
if (hp_probe1(dev, ioaddr) == 0)
return 0;
}
}
return ENODEV;
}
#endif
int hpprobe1(struct device *dev, int ioaddr)
int hp_probe1(struct device *dev, int ioaddr)
{
int i, board_id, wordmode;
char *name;
unsigned char *station_addr = dev->dev_addr;
/* Check for the HP physical address, 08 00 09 xx xx xx. */
/* This really isn't good enough: we may pick up HP LANCE boards
......@@ -100,7 +113,7 @@ int hpprobe1(struct device *dev, int ioaddr)
return ENODEV;
/* Set up the parameters based on the board ID.
If you have additional mappings, please mail them to becker@super.org. */
If you have additional mappings, please mail them to me -djb. */
if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
name = "HP27247";
wordmode = 1;
......@@ -109,13 +122,16 @@ int hpprobe1(struct device *dev, int ioaddr)
wordmode = 0;
}
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 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));
printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
/* Snarf the interrupt now. Someday this could be moved to open(). */
if (dev->irq < 2) {
......
This diff is collapsed.
......@@ -9,7 +9,7 @@
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
* Donald Becker, <becker@cesdis.gsfc.nasa.gov>
*
* Alan Cox : Fixed oddments for NET3.014
*
......
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/*
Written 1992,1993 by Donald Becker.
Written 1992-94 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.
Director, National Security Agency.
This driver should work with many 8390-based ethernet boards. Currently
it support the NE1000, NE2000, clones, and some Cabletron products.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
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@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This driver should work with many programmed-I/O 8390-based ethernet
boards. Currently it support the NE1000, NE2000, many clones,
and some Cabletron products.
*/
/* Routines for the NatSemi-based designs (NE[12]000). */
static char *version =
"ne.c:v0.99-15k 3/3/94 Donald Becker (becker@super.org)\n";
"ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -28,11 +31,28 @@ static char *version =
#include <linux/netdevice.h>
#include "8390.h"
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int netcard_portlist[] =
{ 0x300, 0x280, 0x320, 0x340, 0x360, 0};
/* A list of bad clones that we none-the-less recognize. */
static struct { char *name8, *name16; unsigned char SAprefix[4];}
bad_clone_list[] = {
{"DE100", "DE200", {0x00, 0xDE, 0x01,}},
{"DE120", "DE220", {0x00, 0x80, 0xc8,}},
{"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */
{0,}
};
#define NE_BASE (dev->base_addr)
#define NE_CMD 0x00
#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */
#define NE_IO_EXTENT 0x20
#define NE1SM_START_PG 0x20 /* First page of TX buffer */
#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
......@@ -40,7 +60,7 @@ static char *version =
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
int ne_probe(struct device *dev);
static int neprobe1(int ioaddr, struct device *dev, int verbose);
static int ne_probe1(struct device *dev, int ioaddr);
static void ne_reset_8390(struct device *dev);
static int ne_block_input(struct device *dev, int count,
......@@ -70,44 +90,47 @@ static void ne_block_output(struct device *dev, const int count,
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */
#ifdef HAVE_DEVLIST
struct netdev_entry netcard_drv =
{"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist};
#else
int ne_probe(struct device *dev)
{
int *port, ports[] = {0x300, 0x280, 0x320, 0x340, 0x360, 0};
short ioaddr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (ioaddr < 0)
return ENXIO; /* Don't probe at all. */
if (ioaddr > 0x100)
return ! neprobe1(ioaddr, dev, 1);
if (base_addr > 0x1ff) /* Check a single specified location. */
return ne_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
#ifdef HAVE_PORTRESERVE
if (check_region(*port, 32))
for (i = 0; netcard_portlist[i]; i++) {
int ioaddr = netcard_portlist[i];
if (check_region(ioaddr, NE_IO_EXTENT))
continue;
#endif
if (inb_p(*port) != 0xff && neprobe1(*port, dev, 0)) {
dev->base_addr = *port;
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
}
dev->base_addr = ioaddr;
return ENODEV;
}
#endif
static int neprobe1(int ioaddr, struct device *dev, int verbose)
static int ne_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned char SA_prom[32];
int wordlength = 2;
char *name;
char *name = NULL;
int start_page, stop_page;
int neX000, ctron, dlink, dfi;
int neX000, ctron;
int reg0 = inb(ioaddr);
if ( reg0 == 0xFF)
return 0;
return ENODEV;
/* Do a quick preliminary check that we have a 8390. */
/* Do a preliminary verification that we have a 8390. */
{ int regd;
outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
regd = inb_p(ioaddr + 0x0d);
......@@ -117,14 +140,13 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
outb_p(reg0, ioaddr);
outb(regd, ioaddr + 0x0d); /* Restore the old values. */
return 0;
return ENODEV;
}
}
printk("NE*000 ethercard probe at %#3x:", ioaddr);
/* Read the 16 bytes of station address prom, returning 1 for
an eight-bit interface and 2 for a 16-bit interface.
/* Read the 16 bytes of station address PROM.
We must first initialize registers, similar to NS8390_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
......@@ -162,43 +184,53 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
/* Un-double the SA_prom values. */
for (i = 0; i < 16; i++)
SA_prom[i] = SA_prom[i+i];
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
} else {
start_page = NE1SM_START_PG;
stop_page = NE1SM_STOP_PG;
}
#if defined(show_all_SAPROM)
/* If your ethercard isn't detected define this to see the SA_PROM. */
for(i = 0; i < sizeof(SA_prom); i++)
printk(" %2.2x", SA_prom[i]);
#else
for(i = 0; i < ETHER_ADDR_LEN; i++) {
dev->dev_addr[i] = SA_prom[i];
printk(" %2.2x", SA_prom[i]);
}
#endif
neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01);
dfi = (SA_prom[0] == 'D' && SA_prom[1] == 'F' && SA_prom[2] == 'I');
/* Set up the rest of the parameters. */
if (neX000 || dlink || dfi) {
if (wordlength == 2) {
name = dlink ? "DE200" : "NE2000";
start_page = NESM_START_PG;
stop_page = NESM_STOP_PG;
} else {
name = dlink ? "DE100" : "NE1000";
start_page = NE1SM_START_PG;
stop_page = NE1SM_STOP_PG;
}
if (neX000) {
name = (wordlength == 2) ? "NE2000" : "NE1000";
} else if (ctron) {
name = "Cabletron";
start_page = 0x01;
stop_page = (wordlength == 2) ? 0x40 : 0x20;
} else {
printk(" not found.\n");
return 0;
/* Ack! Well, there might be a *bad* NE*000 clone there.
Check for total bogus addresses. */
for (i = 0; bad_clone_list[i].name8; i++) {
if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
SA_prom[2] == bad_clone_list[i].SAprefix[2]) {
if (wordlength == 2) {
name = bad_clone_list[i].name16;
} else {
name = bad_clone_list[i].name8;
}
break;
}
}
if (bad_clone_list[i].name8 == NULL) {
printk(" not found (invalid signature %2.2x %2.2x).\n",
SA_prom[14], SA_prom[15]);
return ENXIO;
}
}
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
if (dev->irq < 2) {
autoirq_setup(0);
......@@ -221,15 +253,16 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
int irqval = request_irq (dev->irq, ei_interrupt, 0, "ne");
if (irqval) {
printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
return 0;
return EAGAIN;
}
}
dev->base_addr = ioaddr;
#ifdef HAVE_PORTRESERVE
snarf_region(ioaddr, 32);
#endif
snarf_region(ioaddr, NE_IO_EXTENT);
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = SA_prom[i];
ethdev_init(dev);
printk("\n%s: %s found at %#x, using IRQ %d.\n",
......@@ -253,7 +286,7 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
ei_status.block_input = &ne_block_input;
ei_status.block_output = &ne_block_output;
NS8390_init(dev, 0);
return dev->base_addr;
return 0;
}
/* Hard reset the card. This used to pause for the same period that a
......@@ -289,9 +322,10 @@ ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
if (ei_status.dmaing) {
if (ei_debug > 0)
printk("%s: DMAing conflict in ne_block_input."
"[DMAstat:%1x][irqlock:%1x]\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
printk("%s: DMAing conflict in ne_block_input "
"[DMAstat:%d][irqlock:%d][intr:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
dev->interrupt);
return 0;
}
ei_status.dmaing |= 0x01;
......@@ -348,8 +382,9 @@ ne_block_output(struct device *dev, int count,
if (ei_status.dmaing) {
if (ei_debug > 0)
printk("%s: DMAing conflict in ne_block_output."
"[DMAstat:%1x][irqlock:%1x]\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
"[DMAstat:%d][irqlock:%d][intr:%d]\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
dev->interrupt);
return;
}
ei_status.dmaing |= 0x02;
......
/* netdrv_init.c: Initialization for network devices. */
/*
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,
incorporated herein by reference.
Written 1993,1994 by Donald Becker.
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@cesdis.gsfc.nasa.gov or
C/O Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This file contains the initialization for the "pl14+" style ethernet
drivers. It should eventually replace most of drivers/net/Space.c.
......@@ -95,7 +92,10 @@ init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp)
if (dev == NULL) {
int alloc_size = sizeof(struct device) + sizeof("eth%d ")
+ sizeof_private;
+ sizeof_private + 3;
alloc_size &= ~3; /* Round to dword boundary. */
if (mem_startp && *mem_startp ) {
dev = (struct device *)*mem_startp;
*mem_startp += alloc_size;
......
/* skeleton.c: A sample network driver core for linux. */
/* skeleton.c: A network driver outline 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,
incorporated herein by reference.
Written 1993-94 by Donald Becker.
The author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
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.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This file is an outline for writing a network device driver for the
the Linux operating system.
......@@ -19,7 +22,7 @@
*/
static char *version =
"skeleton.c:v0.05 11/16/93 Donald Becker (becker@super.org)\n";
"skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
/* Always include 'config.h' first in case the user wants to turn on
or override something. */
......@@ -59,20 +62,13 @@ static char *version =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
#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_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size); do ; while (0)
#endif
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int netcard_portlist[] =
{ 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
......@@ -80,15 +76,15 @@ extern struct device *irq2dev_map[16];
#endif
static unsigned int net_debug = NET_DEBUG;
/* The number of low I/O ports used by the ethercard. */
#define NETCARD_IO_EXTENT 32
/* Information that need to be kept for each board. */
struct net_local {
struct enet_statistics stats;
long open_time; /* Useless example local info. */
};
/* The number of low I/O ports used by the ethercard. */
#define ETHERCARD_TOTAL_SIZE 16
/* The station (ethernet) address prefix, used for IDing the board. */
#define SA_ADDR0 0x00
#define SA_ADDR1 0x42
......@@ -98,7 +94,7 @@ struct net_local {
extern int netcard_probe(struct device *dev);
static int netcard_probe1(struct device *dev, short ioaddr);
static int netcard_probe1(struct device *dev, int ioaddr);
static int net_open(struct device *dev);
static int net_send_packet(struct sk_buff *skb, struct device *dev);
static void net_interrupt(int reg_ptr);
......@@ -119,54 +115,75 @@ extern void chipset_init(struct device *dev, int startp);
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
#ifdef HAVE_DEVLIST
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
struct netdev_entry netcard_drv =
{"netcard", netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
#else
int
netcard_probe(struct device *dev)
{
int *port, ports[] = {0x300, 0x280, 0};
int base_addr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (base_addr > 0x1ff) /* Check a single specified location. */
return netcard_probe1(dev, base_addr);
else if (base_addr > 0) /* Don't probe at all. */
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
int ioaddr = *port;
if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
continue;
if (inb(ioaddr) != 0x57)
for (i = 0; netcard_portlist[i]; i++) {
int ioaddr = netcard_portlist[i];
if (check_region(ioaddr, NETCARD_IO_EXTENT))
continue;
dev->base_addr = ioaddr;
if (netcard_probe1(dev, ioaddr) == 0)
return 0;
}
dev->base_addr = base_addr;
return ENODEV;
}
#endif
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions. */
int netcard_probe1(struct device *dev, short ioaddr)
static int netcard_probe1(struct device *dev, int ioaddr)
{
unsigned char station_addr[6];
static unsigned version_printed = 0;
int i;
/* Read the station address PROM. */
for (i = 0; i < 6; i++) {
station_addr[i] = inb(ioaddr + i);
}
/* Check the first three octets of the S.A. for the manufacturer's code. */
if (station_addr[0] != SA_ADDR0
|| station_addr[1] != SA_ADDR1 || station_addr[2] != SA_ADDR2) {
/* For ethernet adaptors the first three octets of the station address contains
the manufacturer's unique code. That might be a good probe method.
Ideally you would add additional checks. */
if (inb(ioaddr + 0) != SA_ADDR0
|| inb(ioaddr + 1) != SA_ADDR1
|| inb(ioaddr + 2) != SA_ADDR2) {
return ENODEV;
}
printk("%s: %s found at %#3x, IRQ %d.\n", dev->name,
"network card", dev->base_addr, dev->irq);
/* Allocate a new 'dev' if needed. */
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct net_local), 0);
if (net_debug && version_printed++ == 0)
printk(version);
printk("%s: %s found at %#3x, ", dev->name, "network card", ioaddr);
/* Fill in the 'dev' fields. */
dev->base_addr = ioaddr;
/* Retrive and print the ethernet address. */
for (i = 0; i < 6; i++)
printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
#ifdef jumpered_interrupts
/* If this board has jumpered interrupts, snarf the interrupt vector
now. There is no point in waiting since no other device can use
the interrupt, and this marks the irq as busy. */
the interrupt, and this marks the irq as busy.
Jumpered interrupts are typically not reported by the boards, and
we must used autoIRQ to find them. */
if (dev->irq == -1)
; /* Do nothing: a user-level program will set it. */
......@@ -190,14 +207,50 @@ int netcard_probe1(struct device *dev, short ioaddr)
}
}
#endif /* jumpered interrupt */
#ifdef jumpered_dma
/* If we use a jumpered DMA channel, that should be probed for and
allocated here as well. See lance.c for an example. */
if (dev->dma == 0) {
if (request_dma(dev->dma, "netcard")) {
printk("DMA %d allocation failed.\n", dev->dma);
return EAGAIN;
} else
printk(", assigned DMA %d.\n", dev->dma);
} else {
short dma_status, new_dma_status;
/* Read the DMA channel status registers. */
dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
(inb(DMA2_STAT_REG) & 0xf0);
/* Trigger a DMA request, perhaps pause a bit. */
outw(0x1234, ioaddr + 8);
/* Re-read the DMA status registers. */
new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
(inb(DMA2_STAT_REG) & 0xf0);
/* Eliminate the old and floating requests and DMA4, the cascade. */
new_dma_status ^= dma_status;
new_dma_status &= ~0x10;
for (i = 7; i > 0; i--)
if (test_bit(new_dma, &new_dma_status)) {
dev->dma = i;
break;
}
if (i <= 0) {
printk("DMA probe failed.\n");
return EAGAIN;
}
if (request_dma(dev->dma, "netcard")) {
printk("probed DMA %d allocation failed.\n", dev->dma);
return EAGAIN;
}
}
#endif /* jumpered DMA */
/* Grab the region so we can find another board if autoIRQ fails. */
snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
if (net_debug)
printk(version);
snarf_region(ioaddr, NETCARD_IO_EXTENT);
/* Initialize the device structure. */
if (dev->priv == NULL)
dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
memset(dev->priv, 0, sizeof(struct net_local));
......@@ -207,8 +260,7 @@ int netcard_probe1(struct device *dev, short ioaddr)
dev->get_stats = net_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* Fill in the fields of the device structure with ethernet-generic values. */
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
return 0;
......@@ -234,15 +286,14 @@ net_open(struct device *dev)
return -EAGAIN;
}
/* Always snarf a DMA channel after the IRQ. */
/* Always snarf the DMA channel after the IRQ, and clean up on failure. */
if (request_dma(dev->dma,"skeleton ethernet")) {
free_irq(dev->irq);
return -EAGAIN;
}
irq2dev_map[dev->irq] = dev;
/* Reset the hardware here. */
/* Reset the hardware here. Don't forget to set the station address. */
/*chipset_init(dev, 1);*/
outb(0x00, ioaddr);
lp->open_time = jiffies;
......@@ -337,6 +388,7 @@ net_interrupt(int reg_ptr)
}
} while (++boguscount < 20) ;
dev->interrupt = 0;
return;
}
......
/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
/*
Written 1993 by Donald Becker. If released, this code will be
Written 1993-94 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.
Director, National Security Agency.
This is a driver for the SMC Ultra ethercard.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
The Author may be reached as becker@super.org or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
This is a driver for the SMC Ultra ethercard.
*/
static char *version =
"smc-ultra.c:v0.07 3/1/94 Donald Becker (becker@super.org)\n";
"smc-ultra.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -26,15 +29,15 @@ static char *version =
#include <linux/netdevice.h>
#include "8390.h"
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
/* Compatibility definitions for earlier kernel versions. */
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size); do ; while (0)
#endif
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int ultra_portlist[] =
{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
int ultraprobe(int ioaddr, struct device *dev);
int ultraprobe1(int ioaddr, struct device *dev);
int ultra_probe(struct device *dev);
int ultra_probe1(struct device *dev, int ioaddr);
static int ultra_open(struct device *dev);
static void ultra_reset_8390(struct device *dev);
......@@ -51,43 +54,51 @@ static int ultra_close_card(struct device *dev);
#define ULTRA_RESET 0x80 /* Board reset, in ULTRA_CMDREG. */
#define ULTRA_MEMENB 0x40 /* Enable the shared memory. */
#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */
#define ULTRA_IO_EXTENT 32
/* Probe for the Ultra. This looks like a 8013 with the station
address PROM at I/O ports <base>+8 to <base>+13, with a checksum
following.
*/
#ifdef HAVE_DEVLIST
struct netdev_entry ultra_drv =
{"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist};
#else
int ultra_probe(struct device *dev)
{
int *port, ports[] = {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
unsigned short ioaddr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (ioaddr > 0x1ff)
return ultraprobe1(ioaddr, dev);
else if (ioaddr > 0)
return ENXIO; /* Don't probe at all. */
if (base_addr > 0x1ff) /* Check a single specified location. */
return ultra_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
if (check_region(*port, 32))
for (i = 0; ultra_portlist[i]; i++) {
int ioaddr = ultra_portlist[i];
if (check_region(ioaddr, ULTRA_IO_EXTENT))
continue;
if ((inb(*port + 7) & 0xF0) == 0x20 /* Check chip ID nibble. */
&& ultraprobe1(*port, dev) == 0)
if (ultra_probe1(dev, ioaddr) == 0)
return 0;
}
dev->base_addr = ioaddr;
return ENODEV;
}
#endif
int ultraprobe1(int ioaddr, struct device *dev)
int ultra_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned char *station_addr = dev->dev_addr;
int checksum = 0;
char *model_name;
unsigned char eeprom_irq = 0;
/* Values from various config regs. */
unsigned char num_pages, irqreg, addr, reg4 = inb(ioaddr + 4) & 0x7f;
/* Check the ID nibble. */
if ((inb(ioaddr + 7) & 0xF0) != 0x20)
return ENODEV;
/* Select the station address register set. */
outb(reg4, ioaddr + 4);
......@@ -97,15 +108,19 @@ int ultraprobe1(int ioaddr, struct device *dev)
if ((checksum & 0xff) != 0xFF)
return ENODEV;
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
printk("%s: SMC Ultra at %#3x,", dev->name, ioaddr);
for (i = 0; i < 6; i++)
printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
/* Switch from the station address to the alternate register set and
read the useful registers there. */
outb(0x80 | reg4, ioaddr + 4);
/* Enabled FINE16 mode to avoid BIOS ROM width mismatches during reboot. */
/* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
irqreg = inb(ioaddr + 0xd);
addr = inb(ioaddr + 0xb);
......@@ -264,5 +279,7 @@ ultra_close_card(struct device *dev)
* compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c"
* version-control: t
* kept-new-versions: 5
* c-indent-level: 4
* tab-width: 4
* End:
*/
/* wd.c: A WD80x3 ethernet driver for linux. */
/*
Written 1993 by Donald Becker.
Written 1993-94 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.
Director, National Security Agency.
This is a driver for WD8003 and WD8013 "compatible" ethercards.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
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@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
This is a driver for WD8003 and WD8013 "compatible" ethercards.
Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
*/
static char *version =
"wd.c:v0.99-14 11/21/93 Donald Becker (becker@super.org)\n";
"wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -27,15 +30,15 @@ static char *version =
#include <linux/netdevice.h>
#include "8390.h"
extern struct device *init_etherdev(struct device *dev, int sizeof_private,
unsigned long *mem_startp);
/* Compatibility definitions for earlier kernel versions. */
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size) do ; while (0)
#endif
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int wd_portlist[] =
{0x300, 0x280, 0x380, 0x240, 0};
int wd_probe(struct device *dev);
int wdprobe1(int ioaddr, struct device *dev);
int wd_probe1(struct device *dev, int ioaddr);
static int wd_open(struct device *dev);
static void wd_reset_8390(struct device *dev);
......@@ -56,42 +59,48 @@ static int wd_close_card(struct device *dev);
#define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */
#define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */
#define NIC16 0x40 /* Enable 16 bit access from the 8390. */
#define WD_NIC_OFFSET 16 /* Offset to the 8390 NIC from the base_addr. */
#define WD_NIC_OFFSET 16 /* Offset to the 8390 from the base_addr. */
#define WD_IO_EXTENT 32
/* Probe for the WD8003 and WD8013. These cards have the station
address PROM at I/O ports <base>+8 to <base>+13, with a checksum
following. A Soundblaster can have the same checksum as an WDethercard,
so we have an extra exclusionary check for it.
The wdprobe1() routine initializes the card and fills the
The wd_probe1() routine initializes the card and fills the
station address field. */
#ifdef HAVE_DEVLIST
struct netdev_entry wd_drv =
{"wd", wd_probe1, WD_IO_EXTENT, wd_portlist};
#else
int wd_probe(struct device *dev)
{
int *port, ports[] = {0x300, 0x280, 0x380, 0x240, 0};
short ioaddr = dev->base_addr;
int i;
int base_addr = dev ? dev->base_addr : 0;
if (ioaddr < 0)
return ENXIO; /* Don't probe at all. */
if (ioaddr > 0x100)
return ! wdprobe1(ioaddr, dev);
if (base_addr > 0x1ff) /* Check a single specified location. */
return wd_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (port = &ports[0]; *port; port++) {
if (check_region(*port, 32))
for (i = 0; wd_portlist[i]; i++) {
int ioaddr = wd_portlist[i];
if (check_region(ioaddr, WD_IO_EXTENT))
continue;
if (inb(*port + 8) != 0xff
&& inb(*port + 9) != 0xff /* Extra check to avoid soundcard. */
&& wdprobe1(*port, dev))
if (wd_probe1(dev, ioaddr) == 0)
return 0;
}
dev->base_addr = ioaddr;
return ENODEV;
}
#endif
int wdprobe1(int ioaddr, struct device *dev)
int wd_probe1(struct device *dev, int ioaddr)
{
int i;
unsigned char *station_addr = dev->dev_addr;
int checksum = 0;
int ancient = 0; /* An old card without config registers. */
int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */
......@@ -99,12 +108,17 @@ int wdprobe1(int ioaddr, struct device *dev)
for (i = 0; i < 8; i++)
checksum += inb(ioaddr + 8 + i);
if ((checksum & 0xff) != 0xFF)
return 0;
if (inb(ioaddr + 8) == 0xff /* Extra check to avoid soundcard. */
|| inb(ioaddr + 9) == 0xff
|| (checksum & 0xff) != 0xFF)
return ENODEV;
if (dev == NULL)
dev = init_etherdev(0, sizeof(struct ei_device), 0);
printk("%s: WD80x3 at %#3x, ", dev->name, ioaddr);
for (i = 0; i < 6; i++)
printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
/* The following PureData probe code was contributed by
Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
......@@ -218,11 +232,11 @@ int wdprobe1(int ioaddr, struct device *dev)
share and the board will usually be enabled. */
if (request_irq(dev->irq, ei_interrupt, 0, "wd")) {
printk (" unable to get IRQ %d.\n", dev->irq);
return 0;
return EAGAIN;
}
/* OK, were are certain this is going to work. Setup the device. */
snarf_region(ioaddr, 32);
snarf_region(ioaddr, WD_IO_EXTENT);
ethdev_init(dev);
ei_status.name = model_name;
......@@ -248,7 +262,7 @@ int wdprobe1(int ioaddr, struct device *dev)
dev->stop = &wd_close_card;
NS8390_init(dev, 0);
return dev->base_addr;
return 0;
}
static int
......
/* znet.c: An Zenith Z-Note ethernet driver for linux. */
static char *version = "znet.c:v1.01 7/1/94 becker@cesdis.gsfc.nasa.gov\n";
static char *version = "znet.c:v1.02 9/23/94 becker@cesdis.gsfc.nasa.gov\n";
/*
Written by Donald Becker.
......@@ -81,7 +81,7 @@ static char *version = "znet.c:v1.01 7/1/94 becker@cesdis.gsfc.nasa.gov\n";
#include <linux/if_arp.h>
#ifndef ZNET_DEBUG
#define ZNET_DEBUG 3
#define ZNET_DEBUG 1
#endif
static unsigned int znet_debug = ZNET_DEBUG;
......
......@@ -1804,7 +1804,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end
host->hostt->cmd_per_lun;
if(host->unchecked_isa_dma &&
memory_end > ISA_DMA_THRESHOLD &&
memory_end - 1 > ISA_DMA_THRESHOLD &&
SDpnt->type != TYPE_TAPE) {
dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
host->hostt->cmd_per_lun;
......
......@@ -209,7 +209,9 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int
size + 1024, 1, 0, NULL,
/* Here is NFS_SLACK_SPACE..., hack */
&addrlen);
if (result < addrlen) {
if (result < 0) {
printk("NFS: notice message: result=%d\n", result);
} else if (result < addrlen) {
printk("NFS: just caught a too small read memory size..., email to NET channel\n");
printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
result = -EIO;
......
......@@ -71,10 +71,16 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
}
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
&res, &len, NFS_MAXPATHLEN);
#if 1
if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
printk("NFS: no memory in nfs_follow_link\n");
error = -EIO;
}
#else
while ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
schedule();
}
#endif
if (error) {
iput(inode);
iput(dir);
......
......@@ -54,7 +54,7 @@ struct rusage {
#define RLIM_NLIMITS 6
#define RLIM_INFINITY 0x7FFFFFFF
#define RLIM_INFINITY ((long)(~0UL>>1))
struct rlimit {
int rlim_cur;
......
......@@ -13,7 +13,7 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGUNUSED 7
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
......@@ -29,32 +29,19 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
/*
* Most of these aren't used yet (and perhaps never will),
* so they are commented out.
*/
#define SIGIO 23
#define SIGPOLL SIGIO
#define SIGURG SIGIO
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
/*
#define SIGLOST 29
*/
#define SIGPWR 30
/* Arggh. Bad user source code wants this.. */
#define SIGBUS SIGUNUSED
#define SIGUNUSED 31
/*
* sa_flags values: SA_STACK is not currently supported, but will allow the
......
......@@ -600,7 +600,7 @@ static void do_timer(struct pt_regs * regs)
unsigned long mask;
struct timer_struct *tp;
long ltemp;
long ltemp, psecs;
/* Advance the phase, once it gets to one microsecond, then
* advance the tick more.
......@@ -679,12 +679,20 @@ static void do_timer(struct pt_regs * regs)
/*
* check the cpu time limit on the process.
*/
if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
(((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_cur))
send_sig(SIGXCPU, current, 1);
if ((current->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
(((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_max))
send_sig(SIGKILL, current, 1);
if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
(((current->stime + current->utime) % HZ) == 0)) {
psecs = (current->stime + current->utime) / HZ;
/* send when equal */
if (psecs == current->rlim[RLIMIT_CPU].rlim_cur)
send_sig(SIGXCPU, current, 1);
/* and every five seconds thereafter. */
else if ((psecs > current->rlim[RLIMIT_CPU].rlim_cur) &&
((psecs - current->rlim[RLIMIT_CPU].rlim_cur) % 5) == 0)
send_sig(SIGXCPU, current, 1);
}
if (current != task[0] && 0 > --current->counter) {
current->counter = 0;
......
......@@ -217,8 +217,8 @@ if (!(context.x & 0xfffc) || (context.x & 3) != 3) goto badframe; COPY(x);
COPY(ebx);
COPY(esp); COPY(ebp);
COPY(edi); COPY(esi);
regs->eflags &= ~0xCD5;
regs->eflags |= context.eflags & 0xCD5;
regs->eflags &= ~0x40DD5;
regs->eflags |= context.eflags & 0x40DD5;
regs->orig_eax = -1; /* disable syscall checks */
return context.eax;
badframe:
......
......@@ -45,8 +45,8 @@
#define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
#define SAFE_MASK (0xDD5)
#define RETURN_MASK (0xDFF)
#define SAFE_MASK (0x40DD5)
#define RETURN_MASK (0x40DFF)
asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
{
......
......@@ -23,6 +23,7 @@
* Alan Cox : Removed old debugging junk
* Alan Cox : Fixed the ICMP error status of net/host unreachable
* Gerhard Koerting : Fixed broadcast ping properly
* Ulrich Kunitz : Fixed ICMP timestamp reply
*
*
*
......@@ -425,7 +426,20 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
unsigned long *timeptr, midtime;
struct device *ndev=NULL;
size = dev->hard_header_len + 64 + len;
if (len != 20)
{
printk(
"ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!\n",
len);
icmp_statistics.IcmpInErrors++;
#if 1
/* correct answers are possible for everything >= 12 */
if (len < 12)
#endif
return;
}
size = dev->hard_header_len + 84;
if (! (skb2 = alloc_skb(size, GFP_ATOMIC)))
{
......@@ -454,14 +468,14 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
/*
* Re-adjust length according to actual IP header size.
*/
skb2->len = offset + len;
skb2->len = offset + 20;
/*
* Build ICMP_TIMESTAMP Response message.
*/
icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
memcpy((char *) icmphr, (char *) icmph, len);
memcpy((char *) icmphr, (char *) icmph, 12);
icmphr->type = ICMP_TIMESTAMPREPLY;
icmphr->code = icmphr->checksum = 0;
......@@ -473,7 +487,7 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
*/
timeptr [1] = timeptr [2] = htonl(midtime);
icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, len);
icmphr->checksum = ip_compute_csum((unsigned char *) icmphr, 20);
/*
* Ship it out - free it when done
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment