summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
commitdcec8a13bf565e47942a1751a9cec21bec5648fe (patch)
tree548b69625b18cc2e88c3e68d0923be546c9ebb03 /drivers/net
parent2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff)
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash. o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/3c59x.c18
-rw-r--r--drivers/net/Config.in5
-rw-r--r--drivers/net/Makefile8
-rw-r--r--drivers/net/Space.c4
-rw-r--r--drivers/net/arcnet.c24
-rw-r--r--drivers/net/de4x5.c235
-rw-r--r--drivers/net/defxx.c98
-rw-r--r--drivers/net/defxx.h3
-rw-r--r--drivers/net/dgrs.c17
-rw-r--r--drivers/net/eepro100.c18
-rw-r--r--drivers/net/epic100.c1215
-rw-r--r--drivers/net/hamradio/6pack.c1129
-rw-r--r--drivers/net/hamradio/6pack.h135
-rw-r--r--drivers/net/hamradio/Config.in2
-rw-r--r--drivers/net/hamradio/Makefile8
-rw-r--r--drivers/net/hamradio/soundmodem/gentbl.c2
-rw-r--r--drivers/net/hp100.c142
-rw-r--r--drivers/net/lance.c29
-rw-r--r--drivers/net/mace.c70
-rw-r--r--drivers/net/mace.h2
-rw-r--r--drivers/net/ne.c29
-rw-r--r--drivers/net/pcnet32.c30
-rw-r--r--drivers/net/ppp.c39
-rw-r--r--drivers/net/ppp_deflate.c80
-rw-r--r--drivers/net/sdla_fr.c1
-rw-r--r--drivers/net/sdla_ppp.c1
-rw-r--r--drivers/net/sdla_x25.c1
-rw-r--r--drivers/net/smc-mca.c16
-rw-r--r--drivers/net/smc-ultra32.c3
-rw-r--r--drivers/net/sunhme.c120
-rw-r--r--drivers/net/sunlance.c40
-rw-r--r--drivers/net/tlan.c28
-rw-r--r--drivers/net/tulip.c20
33 files changed, 3140 insertions, 432 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 2694dbb6c..a9ddfa475 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -65,7 +65,6 @@ static int max_interrupt_work = 20;
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/timer.h>
#include <asm/irq.h> /* For NR_IRQS only. */
#include <asm/bitops.h>
@@ -113,6 +112,7 @@ static int max_interrupt_work = 20;
#if LINUX_VERSION_CODE < 0x20115
#define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
#elif defined(MODULE)
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
@@ -532,12 +532,18 @@ static int vortex_scan(struct device *dev)
be best done a central PCI probe dispatch, which wouldn't work
well with the current structure. So instead we detect 3Com cards
in slot order. */
- if (pcibios_present()) {
+ if (pci_present()) {
static int pci_index = 0;
unsigned char pci_bus, pci_device_fn;
for (;pci_index < 0xff; pci_index++) {
- unsigned char pci_irq_line, pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+ unsigned int pci_irq_line;
+ struct pci_dev *pdev;
+#else
+ unsigned char pci_irq_line;
+#endif
+ unsigned char pci_latency;
unsigned short pci_command, new_command, vendor, device;
unsigned int pci_ioaddr;
int board_index = 0;
@@ -550,10 +556,16 @@ static int vortex_scan(struct device *dev)
PCI_VENDOR_ID, &vendor);
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+ pdev = pci_find_slot(pci_bus, pci_device_fn);
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pdev->base_address[0];
+#else
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_INTERRUPT_LINE, &pci_irq_line);
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_COMMAND, &pci_command);
/* Remove I/O space marker in bit 0. */
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index c3bcd09c5..dfe3ed200 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -42,7 +42,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
fi
tristate '3c509/3c579 support' CONFIG_EL3
- tristate '3c590 series (592/595/597) "Vortex" support' CONFIG_VORTEX
+ tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
fi
bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC
@@ -103,8 +103,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
tristate 'Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'TI ThunderLAN support (EXPERIMENTAL)' CONFIG_TLAN
tristate 'Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210
+ tristate 'SMC EtherPower II (EXPERIMENTAL)' CONFIG_EPIC100
+ tristate 'TI ThunderLAN support (EXPERIMENTAL)' CONFIG_TLAN
bool 'Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET
fi
fi
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 47738877f..3bd7f7280 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -581,6 +581,14 @@ else
endif
endif
+ifeq ($(CONFIG_EPIC100),y)
+L_OBJS += epic100.o
+else
+ ifeq ($(CONFIG_EPIC100),m)
+ M_OBJS += epic100.o
+ endif
+endif
+
# If anything built-in uses slhc, then build it into the kernel also.
# If not, but a module uses it, build as a module.
ifdef CONFIG_SLHC_BUILTIN
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 9d880aa4d..b01c6a8a8 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -94,6 +94,7 @@ extern int tlan_probe(struct device *);
extern int mace_probe(struct device *);
extern int cs89x0_probe(struct device *dev);
extern int ethertap_probe(struct device *dev);
+extern int epic100_probe(struct device *dev);
/* Detachable devices ("pocket adaptors") */
extern int atp_init(struct device *);
@@ -287,6 +288,9 @@ __initfunc(static int ethif_probe(struct device *dev))
#ifdef CONFIG_ARM_AM79C961A
&& am79c961_probe(dev)
#endif
+#ifdef CONFIG_EPIC100
+ && epic100_probe(dev)
+#endif
&& 1 ) {
return 1; /* -ENODEV or -EAGAIN would be more accurate. */
}
diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c
index 8a731a6e3..16795257e 100644
--- a/drivers/net/arcnet.c
+++ b/drivers/net/arcnet.c
@@ -18,6 +18,10 @@
**********************
+ v3.01 (98/04/17)
+ - Interrupt handler now also checks dev->[se]dev are non-NULL
+ to avoid crashes in interrupts during card init. [dw]
+
v3.00 (97/11/09)
- Minor cleanup of debugging messages. [mj]
@@ -41,10 +45,10 @@
v2.80 ALPHA (97/08/01)
- Split source into multiple files; generic arcnet support and
- individual chipset drivers. <dwmw2@cam.ac.uk>
+ individual chipset drivers. <Dave@imladris.demon.co.uk>
- v2.61 ALPHA (97/07/30) by David Woodhouse (dwmw2@cam.ac.uk) for
- Nortel (Northern Telecom).
+ v2.61 ALPHA (97/07/30) by David Woodhouse (Dave@imladris.demon.co.uk)
+ for Nortel (Northern Telecom).
- Added support for IO-mapped modes and for SMC COM20020 chipset.
- Fixed (avoided) race condition in send_packet routines which was
discovered when the buffer copy routines got slow (?).
@@ -170,7 +174,7 @@
*/
static const char *version =
- "arcnet.c: v3.00 97/11/09 Avery Pennarun <apenwarr@bond.net> et al.\n";
+ "arcnet.c: v3.01 98/04/24 Avery Pennarun <apenwarr@bond.net> et al.\n";
#include <linux/module.h>
#include <linux/config.h>
@@ -956,20 +960,24 @@ arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
return; /* don't even try. */
}
#ifdef CONFIG_ARCNET_1051
- lp->sdev->interrupt=1;
+ if (lp->sdev)
+ lp->sdev->interrupt=1;
#endif
#ifdef CONFIG_ARCNET_ETH
- lp->edev->interrupt=1;
+ if (lp->edev)
+ lp->edev->interrupt=1;
#endif
/* Call the "real" interrupt handler. */
(*lp->inthandler)(dev);
#ifdef CONFIG_ARCNET_ETH
- lp->edev->interrupt=0;
+ if (lp->edev)
+ lp->edev->interrupt=0;
#endif
#ifdef CONFIG_ARCNET_1051
- lp->sdev->interrupt=0;
+ if (lp->sdev)
+ lp->sdev->interrupt=0;
#endif
if (!test_and_clear_bit(0, (int *)&dev->interrupt))
BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index 6bd5be8b7..c0c52d24f 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -213,7 +213,7 @@
insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
- For a compiled in driver, at or above line 526, place e.g.
+ For a compiled in driver, somewhere in this file, place e.g.
#define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP"
Yes, I know full duplex isn't permissible on BNC or AUI; they're just
@@ -380,6 +380,7 @@
static const char *version = "de4x5.c:V0.536 1998/3/5 davies@maniac.ultranet.com\n";
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -390,7 +391,6 @@ static const char *version = "de4x5.c:V0.536 1998/3/5 davies@maniac.ultranet.com
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -929,7 +929,7 @@ static void SetMulticastFilter(struct device *dev);
static int get_hw_addr(struct device *dev);
static void srom_repair(struct device *dev, int card);
static int test_bad_enet(struct device *dev, int status);
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
static void eisa_probe(struct device *dev, u_long iobase);
#endif
static void pci_probe(struct device *dev, u_long iobase);
@@ -978,12 +978,15 @@ static int loading_module = 0;
#endif /* MODULE */
static char name[DE4X5_NAME_LENGTH + 1];
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
#endif
static int num_de4x5s = 0;
static int cfrv = 0, useSROM = 0;
-static int lastEISA = 0, lastPCI = -1;
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
+static int lastEISA = 0;
+#endif
+static int lastPCI = -1;
static struct device *lastModule = NULL;
/*
@@ -1048,7 +1051,7 @@ de4x5_probe(struct device *dev))
{
u_long iobase = dev->base_addr;
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
eisa_probe(dev, iobase);
#endif
pci_probe(dev, iobase);
@@ -1305,9 +1308,8 @@ de4x5_open(struct device *dev)
lp->state = OPEN;
de4x5_dbg_open(dev);
-
if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ,
- lp->adapter_name, dev)) {
+ lp->adapter_name, dev)) {
printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ,
lp->adapter_name, dev)) {
@@ -1974,7 +1976,7 @@ SetMulticastFilter(struct device *dev)
return;
}
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
/*
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard. Upto 15 EISA devices are supported.
@@ -2063,15 +2065,14 @@ __initfunc(static void
pci_probe(struct device *dev, u_long ioaddr))
{
u_char pb, pbus, dev_num, dnum, dev_fn, timer;
- u_short vendor, index, status;
+ u_short dev_id, vendor, index, status;
u_int irq = 0, device, class = DE4X5_CLASS_CODE;
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
struct bus_type *lp = &bus;
- struct pci_dev *pdev;
if (lastPCI == NO_MORE_PCI) return;
- if (!pcibios_present()) {
+ if (!pci_present()) {
lastPCI = NO_MORE_PCI;
return; /* No PCI bus in this machine! */
}
@@ -2091,77 +2092,92 @@ pci_probe(struct device *dev, u_long ioaddr))
(pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
index++) {
dev_num = PCI_SLOT(dev_fn);
- if ((pbus || dnum) && ((pbus != pb) || (dnum != dev_num))) continue;
- for (pdev = pci_devices; pdev; pdev = pdev->next) {
- if ((pdev->bus->number==pb) && (pdev->devfn==dev_fn)) break;
- }
-
- vendor = pdev->vendor;
- device = pdev->device << 8;
- if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
+ if ((!pbus && !dnum) || ((pbus == pb) && (dnum == dev_num))) {
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,85)
+ struct pci_dev *pdev = pci_find_slot(pb, dev_fn);
+#else
+ u_char tirq;
+ u_int tmp;
+#endif
+ device = 0;
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+ device = dev_id;
+ device <<= 8;
+ if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
+ continue;
+ }
- /* Search for an SROM on this bus */
- if (lp->bus_num != pb) {
- lp->bus_num = pb;
- srom_search(index);
- }
+ /* Search for an SROM on this bus */
+ if (lp->bus_num != pb) {
+ lp->bus_num = pb;
+ srom_search(index);
+ }
- /* Get the chip configuration revision register */
- pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
+ /* Get the chip configuration revision register */
+ pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
- /* Set the device number information */
- lp->device = dev_num;
- lp->bus_num = pb;
+ /* Set the device number information */
+ lp->device = dev_num;
+ lp->bus_num = pb;
- /* Set the chipset information */
- if (is_DC2114x) device |= (cfrv & CFRV_RN);
- lp->chipset = device;
+ /* Set the chipset information */
+ if (is_DC2114x) device |= (cfrv & CFRV_RN);
+ lp->chipset = device;
- /* Get the board I/O address (64 bits on sparc64) */
- iobase = pdev->base_address[0] & CBIO_MASK;
+ /* Get the board I/O address and IRQ */
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,85)
+ pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+ iobase = tmp;
+ pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+ irq = tirq;
+#else
+ iobase = pdev->base_address[0];
+ irq = pdev->irq;
+#endif
+ iobase &= CBIO_MASK;
- /* Fetch the IRQ to be used */
- irq = pdev->irq;
- if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
-
- /* Check if I/O accesses and Bus Mastering are enabled */
- pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
-#ifdef __powerpc__
- if (!(status & PCI_COMMAND_IO)) {
- status |= PCI_COMMAND_IO;
- pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+ if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
+
+ /* Check if I/O accesses and Bus Mastering are enabled */
pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
- }
+#ifdef __powerpc__
+ if (!(status & PCI_COMMAND_IO)) {
+ status |= PCI_COMMAND_IO;
+ pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+ }
#endif /* __powerpc__ */
- if (!(status & PCI_COMMAND_IO)) continue;
+ if (!(status & PCI_COMMAND_IO)) continue;
- if (!(status & PCI_COMMAND_MASTER)) {
- status |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
- pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
- }
- if (!(status & PCI_COMMAND_MASTER)) continue;
+ if (!(status & PCI_COMMAND_MASTER)) {
+ status |= PCI_COMMAND_MASTER;
+ pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status);
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status);
+ }
+ if (!(status & PCI_COMMAND_MASTER)) continue;
- /* Check the latency timer for values >= 0x60 */
- pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
- if (timer < 0x60) {
- pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
- }
+ /* Check the latency timer for values >= 0x60 */
+ pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
+ if (timer < 0x60) {
+ pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
+ }
- DevicePresent(DE4X5_APROM);
- if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
- dev->irq = irq;
- if ((status = de4x5_hw_init(dev, iobase)) == 0) {
- num_de4x5s++;
- if (loading_module) {
- link_modules(lastModule, dev);
- lastPCI = index;
+ DevicePresent(DE4X5_APROM);
+ if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
+ dev->irq = irq;
+ if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+ num_de4x5s++;
+ if (loading_module) {
+ link_modules(lastModule, dev);
+ lastPCI = index;
+ }
+ return;
}
- return;
+ } else if (ioaddr != 0) {
+ printk("%s: region already allocated at 0x%04lx.\n", dev->name,
+ iobase);
}
- } else if (ioaddr != 0) {
- printk("%s: region already allocated at 0x%04lx.\n", dev->name,
- iobase);
}
}
@@ -2180,26 +2196,35 @@ __initfunc(static void
srom_search(int index))
{
u_char pb, dev_fn;
- u_short dev_num, vendor, status;
+ u_short dev_id, dev_num, vendor, status;
u_int irq = 0, device, class = DE4X5_CLASS_CODE;
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
int i, j;
struct bus_type *lp = &bus;
- struct pci_dev *pdev;
+#ifndef __sparc_v9__
+ u_char tirq;
+ u_int tmp;
+#endif
for (;
(pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
index++) {
-
- if (lp->bus_num != pb) return;
- dev_num = PCI_SLOT(dev_fn);
+#ifdef __sparc_v9__
+ struct pci_dev *pdev;
for (pdev = pci_devices; pdev; pdev = pdev->next) {
if ((pdev->bus->number == pb) && (pdev->devfn == dev_fn)) break;
}
-
- vendor = pdev->vendor;
- device = pdev->device << 8;
- if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
+#endif
+ if (lp->bus_num != pb) return;
+ dev_num = PCI_SLOT(dev_fn);
+ device = 0;
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+ device = dev_id;
+ device <<= 8;
+ if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) {
+ continue;
+ }
/* Get the chip configuration revision register */
pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv);
@@ -2213,10 +2238,21 @@ srom_search(int index))
lp->chipset = device;
/* Get the board I/O address (64 bits on sparc64) */
- iobase = pdev->base_address[0] & CBIO_MASK;
+#ifndef __sparc_v9__
+ pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp);
+ iobase = tmp;
+#else
+ iobase = pdev->base_address[0];
+#endif
+ iobase &= CBIO_MASK;
/* Fetch the IRQ to be used */
+#ifndef __sparc_v9__
+ pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+ irq = tirq;
+#else
irq = pdev->irq;
+#endif
if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
/* Check if I/O accesses are enabled */
@@ -4057,6 +4093,19 @@ get_hw_addr(struct device *dev)
/* If possible, try to fix a broken card - SMC only so far */
srom_repair(dev, broken);
+#ifdef CONFIG_PMAC
+ /* If the address starts with 00 a0, we have to bit-reverse
+ each byte of the address. */
+ if (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0xa0) {
+ for (i = 0; i < ETH_ALEN; ++i) {
+ int x = dev->dev_addr[i];
+ x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
+ x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
+ dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
+ }
+ }
+#endif /* CONFIG_PMAC */
+
/* Test for a bad enet address */
status = test_bad_enet(dev, status);
@@ -5717,32 +5766,30 @@ unlink_modules(struct device *p)
static int
count_adapters(void)
{
- int i, j=0;
+ int i, j;
char name[DE4X5_STRLEN];
- u_char pb, dev_fn;
- u_short vendor;
+ u_char pb, dev_fn, dev_num;
+ u_short dev_id, vendor;
u_int class = DE4X5_CLASS_CODE;
u_int device;
- struct pci_dev *pdev;
-
-#ifndef __sparc_v9__
+#if !defined(__sparc_v9__) && !defined(__powerpc__)
u_long iobase = 0x1000;
- for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
+ for (j=0, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
if (EISA_signature(name, EISA_ID)) j++;
}
#endif
- if (!pcibios_present()) return j;
+ if (!pci_present()) return j;
for (i=0;
(pcibios_find_class(class, i, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
i++) {
- for (pdev = pci_devices; pdev; pdev = pdev->next) {
- if ((pdev->bus->number==pb) && (pdev->devfn==dev_fn)) break;
- }
-
- vendor = pdev->vendor;
- device = pdev->device << 8;
+ dev_num = PCI_SLOT(dev_fn);
+ device = 0;
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id);
+ device = dev_id;
+ device <<= 8;
if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++;
}
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 8c2cbd278..2faccc6fd 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -213,7 +213,6 @@ static const char *version = "defxx.c:v1.04 09/16/96 Lawrence V. Stefani (stefa
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <asm/byteorder.h>
@@ -455,9 +454,8 @@ __initfunc(int dfx_probe(
int i; /* used in for loops */
int version_disp; /* was version info string already displayed? */
int port_len; /* length of port address range (in bytes) */
- u8 pci_bus; /* PCI bus number (0-255) */
- u8 pci_dev_fun; /* PCI device and function numbers (0-255) */
u16 port; /* temporary I/O (port) address */
+ struct pci_dev * pdev = NULL; /* PCI device record */
u16 command; /* PCI Configuration space Command register val */
u32 slot_id; /* EISA hardware (slot) ID read from adapter */
DFX_board_t *bp; /* board pointer */
@@ -530,61 +528,58 @@ __initfunc(int dfx_probe(
/* Scan for FDDI PCI controllers */
- if (pcibios_present()) /* is PCI BIOS even present? */
- for (i=0; i < DFX_MAX_NUM_BOARDS; i++) /* scan for up to 8 PCI cards */
- if (pcibios_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, i, &pci_bus, &pci_dev_fun) == 0)
+ if (pci_present()) /* is PCI even present? */
+ while ((pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, pdev)))
+ {
+ if (!version_disp) /* display version info if adapter is found */
{
- if (!version_disp) /* display version info if adapter is found */
- {
- version_disp = 1; /* set display flag to TRUE so that */
- printk(version); /* we only display this string ONCE */
- }
+ version_disp = 1; /* set display flag to TRUE so that */
+ printk(version); /* we only display this string ONCE */
+ }
- /* Verify that I/O enable bit is set (PCI slot is enabled) */
+ /* Verify that I/O enable bit is set (PCI slot is enabled) */
- pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, &command);
- if ((command & PCI_COMMAND_IO) == 0)
- printk("I/O enable bit not set! Verify that slot is enabled\n");
- else
- {
- /* Turn off memory mapped space and enable mastering */
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ if ((command & PCI_COMMAND_IO) == 0)
+ printk("I/O enable bit not set! Verify that slot is enabled\n");
+ else
+ {
+ /* Turn off memory mapped space and enable mastering */
- command |= PCI_COMMAND_MASTER;
- command &= ~PCI_COMMAND_MEMORY;
- pcibios_write_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, command);
+ command |= PCI_COMMAND_MASTER;
+ command &= ~PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, command);
- /* Read I/O base address from PCI Configuration Space */
-
- pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_BASE_ADDRESS_1, &port);
- port &= PCI_BASE_ADDRESS_IO_MASK; /* clear I/O bit (bit 0) */
+ /* Get I/O base address from PCI Configuration Space */
+
+ port = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
- /* Verify port address range is not already being used */
+ /* Verify port address range is not already being used */
+
+ port_len = PFI_K_CSR_IO_LEN;
+ if (check_region(port, port_len) == 0)
+ {
+ /* Allocate a new device structure for this adapter */
- port_len = PFI_K_CSR_IO_LEN;
- if (check_region(port, port_len) == 0)
+ dev = dfx_alloc_device(dev, port);
+ if (dev != NULL)
{
- /* Allocate a new device structure for this adapter */
-
- dev = dfx_alloc_device(dev, port);
- if (dev != NULL)
- {
- /* Initialize board structure with bus-specific info */
-
- bp = (DFX_board_t *) dev->priv;
- bp->dev = dev;
- bp->bus_type = DFX_BUS_TYPE_PCI;
- bp->pci_bus = pci_bus;
- bp->pci_dev_fun = pci_dev_fun;
- if (dfx_driver_init(dev) == DFX_K_SUCCESS)
- num_boards++; /* only increment global board count on success */
- else
- dev->base_addr = 0; /* clear port address field in device structure on failure */
- }
+ /* Initialize board structure with bus-specific info */
+
+ bp = (DFX_board_t *) dev->priv;
+ bp->dev = dev;
+ bp->bus_type = DFX_BUS_TYPE_PCI;
+ bp->pci_dev = pdev;
+ if (dfx_driver_init(dev) == DFX_K_SUCCESS)
+ num_boards++; /* only increment global board count on success */
+ else
+ dev->base_addr = 0; /* clear port address field in device structure on failure */
}
- else
- printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
}
+ else
+ printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
}
+ }
/*
* If we're at this point we're going through dfx_probe() for the first
@@ -823,18 +818,19 @@ __initfunc(void dfx_bus_init(
}
else
{
+ struct pci_dev *pdev = bp->pci_dev;
+
/* Get the interrupt level from the PCI Configuration Table */
- pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_INTERRUPT_LINE, &val);
- dev->irq = val; /* save IRQ value in device table */
+ dev->irq = pdev->irq;
/* Check Latency Timer and set if less than minimal */
- pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, &val);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
if (val < PFI_K_LAT_TIMER_MIN) /* if less than min, override with default */
{
val = PFI_K_LAT_TIMER_DEF;
- pcibios_write_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, val);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
}
/* Enable interrupts at PCI bus interface chip (PFI) */
diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h
index 83d66456b..5707ad877 100644
--- a/drivers/net/defxx.h
+++ b/drivers/net/defxx.h
@@ -1754,8 +1754,7 @@ typedef struct DFX_board_tag
struct device *dev; /* pointer to device structure */
u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */
u16 base_addr; /* base I/O address (same as dev->base_addr) */
- u8 pci_bus; /* PCI bus number */
- u8 pci_dev_fun; /* PCI device and function numbers */
+ struct pci_dev * pci_dev;
u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */
u32 req_ttrt; /* requested TTRT value (in 80ns units) */
u32 burst_size; /* adapter burst size (enumerated) */
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index e562446e8..c379b3a43 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -87,7 +87,6 @@ static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $";
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
@@ -109,6 +108,7 @@ static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $";
#define COPY_FROM_USER(DST,SRC,LEN) copy_from_user(DST,SRC,LEN)
#define COPY_TO_USER(DST,SRC,LEN) copy_to_user(DST,SRC,LEN)
#else
+ #include <linux/bios32.h>
#define IOREMAP(ADDR, LEN) vremap(ADDR, LEN)
#define IOUNMAP(ADDR) vfree(ADDR)
#define COPY_FROM_USER(DST,SRC,LEN) memcpy_fromfs(DST,SRC,LEN)
@@ -1373,14 +1373,19 @@ dgrs_scan(struct device *dev))
/*
* First, check for PCI boards
*/
- if (pcibios_present())
+ if (pci_present())
{
int pci_index = 0;
for (; pci_index < 8; pci_index++)
{
uchar pci_bus, pci_device_fn;
+#if LINUX_VERSION_CODE < 0x20100
uchar pci_irq;
+#else
+ uint pci_irq;
+ struct pci_dev *pdev;
+#endif
uchar pci_latency;
ushort pci_command;
@@ -1390,6 +1395,7 @@ dgrs_scan(struct device *dev))
&pci_device_fn))
break;
+#if LINUX_VERSION_CODE < 0x20100
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_INTERRUPT_LINE, &pci_irq);
pcibios_read_config_dword(pci_bus, pci_device_fn,
@@ -1398,6 +1404,13 @@ dgrs_scan(struct device *dev))
PCI_BASE_ADDRESS_1, &io);
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_2, &mem);
+#else
+ pdev = pci_find_slot(pci_bus, pci_device_fn);
+ pci_irq = pdev->irq;
+ plxreg = pdev->base_address[0];
+ io = pdev->base_address[1];
+ mem = pdev->base_address[2];
+#endif
pcibios_read_config_dword(pci_bus, pci_device_fn,
0x30, &plxdma);
irq = pci_irq;
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 156a07ba2..c896844b2 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -59,7 +59,6 @@ static int max_interrupt_work = 200;
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
@@ -120,6 +119,7 @@ struct device *init_etherdev(struct device *dev, int sizeof_priv,
#if (LINUX_VERSION_CODE < 0x20123)
#define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
#endif
/* The total I/O port extent of the board. Nominally 0x18, but rounded up
@@ -473,10 +473,16 @@ int eepro100_init(struct device *dev)
{
int cards_found = 0;
- if (pcibios_present()) {
+ if (pci_present()) {
static int pci_index = 0;
for (; pci_index < 8; pci_index++) {
- unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency;
+ unsigned char pci_bus, pci_device_fn, pci_latency;
+#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
+ unsigned int pci_irq_line;
+ struct pci_dev *pdev;
+#else
+ unsigned char pci_irq_line;
+#endif
#if (LINUX_VERSION_CODE >= VERSION(1,3,44))
int pci_ioaddr;
#else
@@ -489,11 +495,17 @@ int eepro100_init(struct device *dev)
pci_index, &pci_bus,
&pci_device_fn))
break;
+#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
+ pdev = pci_find_slot(pci_bus, pci_device_fn);
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pdev->base_address[1];
+#else
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_INTERRUPT_LINE, &pci_irq_line);
/* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_1, &pci_ioaddr);
+#endif
/* Remove I/O space marker in bit 0. */
pci_ioaddr &= ~3;
if (speedo_debug > 2)
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
new file mode 100644
index 000000000..b6fc14f55
--- /dev/null
+++ b/drivers/net/epic100.c
@@ -0,0 +1,1215 @@
+/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Linux. */
+/*
+ NOTICE: THIS IS THE ALPHA TEST VERSION!
+ Written 1997 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+ All other rights reserved.
+
+ This driver is for the SMC EtherPower II 9432 PCI ethernet adapter based on
+ the SMC83c170.
+
+ 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
+
+ Support and updates available at
+ http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html
+*/
+
+static const char *version =
+"epic100.c:v0.10 10/14/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+
+/* A few user-configurable values. */
+
+/* Keep the ring sizes a power of two for efficiency.
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE 16
+#define RX_RING_SIZE 32
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ Setting to > 1518 effectively disables this feature. */
+static const int rx_copybreak = 200;
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 10;
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT ((2000*HZ)/1000)
+
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+
+/* Bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
+#define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */
+
+#include <linux/config.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <asm/processor.h> /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+ This is only in the support-all-kernels source code. */
+#include <linux/version.h> /* Evil, but neccessary */
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
+#define RUN_AT(x) (x) /* What to put in timer->expires. */
+#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
+#define virt_to_bus(addr) ((unsigned long)addr)
+#define bus_to_virt(addr) ((void*)addr)
+
+#else /* 1.3.0 and later */
+#define RUN_AT(x) (jiffies + (x))
+#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+#endif
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
+#ifdef MODULE
+#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
+char kernel_version[] = UTS_RELEASE;
+#endif
+#else
+#undef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT
+#undef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+#endif /* 1.3.38 */
+
+#if (LINUX_VERSION_CODE >= 0x10344)
+#define NEW_MULTICAST
+#include <linux/delay.h>
+#endif
+
+#ifdef SA_SHIRQ
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
+#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+#else
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
+#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#else
+#ifdef MODULE
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("SMC 82c170 EPIC series Ethernet driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+#endif
+#endif
+
+/* The I/O extent. */
+#define EPIC_TOTAL_SIZE 0x100
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry epic100_drv =
+{"Epic100", epic100_pci_probe, EPIC_TOTAL_SIZE, NULL};
+#endif
+
+static int epic_debug = 1;
+
+/*
+ Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the SMC "EPCI/100", the SMC
+single-chip ethernet controllers for PCI. This chip is used on
+the SMC EtherPower II boards.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board. The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+Note: Kernel versions earlier than 1.3.73 do not support shared PCI
+interrupt lines.
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+IVb. References
+
+http://www.smc.com/components/catalog/smc83c170.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.national.com/pf/DP/DP83840.html
+
+IVc. Errata
+
+*/
+
+#ifndef PCI_VENDOR_ID_SMC
+#define PCI_VENDOR_ID_SMC 0x10B8
+#endif
+#ifndef PCI_DEVICE_ID_SMC_EPIC100
+#define PCI_DEVICE_ID_SMC_EPIC100 0x0005
+#endif
+
+/* The rest of these values should never change. */
+/* Offsets to registers, using the (ugh) SMC names. */
+enum epic_registers {
+ COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
+ TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28, /* Rx error counters. */
+ MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
+ LAN0=64, /* MAC address. */
+ MC0=80, /* Multicast filter table. */
+ RxCtrl=96, TxCtrl=112, TxSTAT=0x74,
+ PRxCDAR=0x84, RxSTAT=0xA4, EarlyRx=0xB0, PTxCDAR=0xC4, TxThresh=0xDC,
+};
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatus {
+ TxIdle=0x40000, RxIdle=0x20000,
+ CntFull=0x0200, TxUnderrun=0x0100,
+ TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
+ RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+};
+
+/* The EPIC100 Rx and Tx buffer descriptors. */
+
+struct epic_tx_desc {
+ s16 status;
+ u16 txlength;
+ u32 bufaddr;
+ u16 buflength;
+ u16 control;
+ u32 next;
+};
+
+struct epic_rx_desc {
+ s16 status;
+ u16 rxlength;
+ u32 bufaddr;
+ u32 buflength;
+ u32 next;
+};
+
+struct epic_private {
+ char devname[8]; /* Used only for kernel debugging. */
+ const char *product_name;
+ struct device *next_module;
+ struct epic_rx_desc rx_ring[RX_RING_SIZE];
+ struct epic_tx_desc tx_ring[TX_RING_SIZE];
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ /* The addresses of receive-in-place skbuffs. */
+ struct sk_buff* rx_skbuff[RX_RING_SIZE];
+ int chip_id;
+ int revision;
+ struct enet_statistics stats;
+ struct timer_list timer; /* Media selection timer. */
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+ unsigned char mc_filter[8];
+ signed char phys[4]; /* MII device addresses. */
+ unsigned int tx_full:1; /* The Tx queue is full. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
+ unsigned int media2:4; /* Secondary monitored media port. */
+ unsigned int medialock:1; /* Don't sense media type. */
+ unsigned int mediasense:1; /* Media sensing in progress. */
+ int pad0, pad1; /* Used for 8-byte alignment */
+};
+
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#ifdef MODULE
+/* Used to pass the full-duplex flag, etc. */
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#endif
+
+static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
+ int chip_id, int options, int card_idx);
+static int epic_open(struct device *dev);
+static int read_eeprom(int ioaddr, int location);
+static int mii_read(int ioaddr, int phy_id, int location);
+static void epic_timer(unsigned long data);
+static void epic_tx_timeout(struct device *dev);
+static void epic_init_ring(struct device *dev);
+static int epic_start_xmit(struct sk_buff *skb, struct device *dev);
+static int epic_rx(struct device *dev);
+static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int epic_close(struct device *dev);
+static struct enet_statistics *epic_get_stats(struct device *dev);
+#ifdef NEW_MULTICAST
+static void set_rx_mode(struct device *dev);
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+
+
+
+#ifdef MODULE
+/* A list of all installed EPIC devices, for removing the driver module. */
+static struct device *root_epic_dev = NULL;
+#endif
+
+int epic100_probe(struct device *dev)
+{
+ int cards_found = 0;
+ static int pci_index = 0; /* Static, for multiple probe calls. */
+
+ /* Ideally we would detect all network cards in slot order. That would
+ be best done a central PCI probe dispatch, which wouldn't work
+ well with the current structure. So instead we detect just the
+ Epic cards in slot order. */
+
+ if (pcibios_present()) {
+ unsigned char pci_bus, pci_device_fn;
+
+ for (;pci_index < 0xff; pci_index++) {
+ unsigned char pci_irq_line, pci_latency;
+ unsigned short pci_command, vendor, device;
+ unsigned int pci_ioaddr, chip_idx = 0;
+
+ if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+#ifdef REVERSE_PROBE_ORDER
+ 0xff - pci_index,
+#else
+ pci_index,
+#endif
+ &pci_bus, &pci_device_fn)
+ != PCIBIOS_SUCCESSFUL)
+ break;
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_VENDOR_ID, &vendor);
+ if (vendor != PCI_VENDOR_ID_SMC)
+ continue;
+
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_DEVICE_ID, &device);
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ /* Remove I/O space marker in bit 0. */
+ pci_ioaddr &= ~3;
+
+ if (device != PCI_DEVICE_ID_SMC_EPIC100) {
+ printk("Unknown SMC PCI ethernet chip type %4.4x detected:"
+ " not configured.\n", device);
+ continue;
+ }
+ if (epic_debug > 2)
+ printk("Found SMC PCI EPIC/100 at I/O %#x, IRQ %d.\n",
+ pci_ioaddr, pci_irq_line);
+
+ if (check_region(pci_ioaddr, EPIC_TOTAL_SIZE))
+ continue;
+
+#ifdef MODULE
+ dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
+ options[cards_found], cards_found);
+#else
+ dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
+ dev ? dev->mem_start : 0, -1);
+#endif
+
+ if (dev) {
+ /* Get and check the bus-master and latency values. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, &pci_command);
+ if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+ printk(" PCI Master Bit has not been set! Setting...\n");
+ pci_command |= PCI_COMMAND_MASTER;
+ pcibios_write_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, pci_command);
+ }
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_LATENCY_TIMER, &pci_latency);
+ if (pci_latency < 10) {
+ printk(" PCI latency timer (CFLT) is unreasonably low at %d."
+ " Setting to 255 clocks.\n", pci_latency);
+ pcibios_write_config_byte(pci_bus, pci_device_fn,
+ PCI_LATENCY_TIMER, 255);
+ } else if (epic_debug > 1)
+ printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency);
+ dev = 0;
+ cards_found++;
+ }
+ }
+ }
+
+#if defined (MODULE)
+ return cards_found;
+#else
+ return cards_found ? 0 : -ENODEV;
+#endif
+}
+
+static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
+ int chip_id, int options, int card_idx)
+{
+ static int did_version = 0; /* Already printed version info. */
+ struct epic_private *tp;
+ int i;
+
+ if (epic_debug > 0 && did_version++ == 0)
+ printk(version);
+
+ dev = init_etherdev(dev, 0);
+
+ printk("%s: SMC EPIC/100 at %#3x, IRQ %d, ", dev->name, ioaddr, irq);
+
+ /* Bring the chip out of low-power mode. */
+ outl(0x0200, ioaddr + GENCTL);
+ /* Magic?! If we don't set this bit the MII interface won't work. */
+ outl(0x0008, ioaddr + TEST1);
+
+ /* This could also be read from the EEPROM. */
+ for (i = 0; i < 3; i++)
+ ((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
+
+ for (i = 0; i < 5; i++)
+ printk("%2.2x:", dev->dev_addr[i]);
+ printk("%2.2x.\n", dev->dev_addr[i]);
+
+ if (epic_debug > 1) {
+ printk("%s: EEPROM contents\n", dev->name);
+ for (i = 0; i < 64; i++)
+ printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : "");
+ }
+
+ /* We do a request_region() to register /proc/ioports info. */
+ request_region(ioaddr, EPIC_TOTAL_SIZE, "SMC EPIC/100");
+
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+
+ /* The data structures must be quadword aligned. */
+ tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
+ memset(tp, 0, sizeof(*tp));
+ dev->priv = tp;
+
+#ifdef MODULE
+ tp->next_module = root_epic_dev;
+ root_epic_dev = dev;
+#endif
+
+ tp->chip_id = chip_id;
+
+ /* Find the connected MII xcvrs.
+ Doing this in open() would allow detecting external xcvrs later, but
+ takes too much time. */
+ {
+ int phy, phy_idx;
+ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+ phy++) {
+ int mii_status = mii_read(ioaddr, phy, 0);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ tp->phys[phy_idx++] = phy;
+ printk("%s: MII transceiver found at address %d.\n",
+ dev->name, phy);
+ }
+ }
+ if (phy_idx == 0) {
+ printk("%s: ***WARNING***: No MII transceiver found!\n",
+ dev->name);
+ /* Use the known PHY address of the EPII. */
+ tp->phys[0] = 3;
+ }
+ }
+
+ /* Leave the chip in low-power mode. */
+ outl(0x0008, ioaddr + GENCTL);
+
+ /* The lower four bits are the media type. */
+ if (options > 0) {
+ tp->full_duplex = (options & 16) ? 1 : 0;
+ tp->default_port = options & 15;
+ if (tp->default_port)
+ tp->medialock = 1;
+ }
+ if (card_idx >= 0) {
+ if (full_duplex[card_idx] >= 0)
+ tp->full_duplex = full_duplex[card_idx];
+ }
+
+ /* The Epic-specific entries in the device structure. */
+ dev->open = &epic_open;
+ dev->hard_start_xmit = &epic_start_xmit;
+ dev->stop = &epic_close;
+ dev->get_stats = &epic_get_stats;
+ dev->set_multicast_list = &set_rx_mode;
+
+ return dev;
+}
+
+/* Serial EEPROM section. */
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x08 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x09
+#define EE_DATA_READ 0x10 /* EEPROM chip data out. */
+#define EE_ENB (0x0001 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+ The 1.2 code is a "nasty" timing loop, but PC compatible machines are
+ *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro. */
+#ifdef _LINUX_DELAY_H
+#define eeprom_delay(nanosec) udelay((nanosec + 999)/1000)
+#else
+#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#endif
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << 6)
+#define EE_READ_CMD (6 << 6)
+#define EE_ERASE_CMD (7 << 6)
+
+static int read_eeprom(int ioaddr, int location)
+{
+ int i;
+ int retval = 0;
+ int ee_addr = ioaddr + EECTL;
+ int read_cmd = location | EE_READ_CMD;
+
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ outl(EE_ENB, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 10; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, ee_addr);
+ eeprom_delay(100);
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay(150);
+ outl(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */
+ eeprom_delay(250);
+ }
+ outl(EE_ENB, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay(100);
+ retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, ee_addr);
+ eeprom_delay(100);
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ return retval;
+}
+
+#define MII_READOP 1
+#define MII_WRITEOP 2
+static int mii_read(int ioaddr, int phy_id, int location)
+{
+ int i;
+
+ outl((phy_id << 9) | (location << 4) | MII_READOP, ioaddr + MIICtrl);
+ /* Typical operation takes < 50 ticks. */
+ for (i = 4000; i > 0; i--)
+ if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0)
+ break;
+ return inw(ioaddr + MIIData);
+}
+
+
+static int
+epic_open(struct device *dev)
+{
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int i;
+ int mii_reg5;
+ int full_duplex = 0;
+
+ /* Soft reset the chip. */
+ outl(0x0001, ioaddr + GENCTL);
+
+#ifdef SA_SHIRQ
+ if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ,
+ "SMC EPIC/100", dev)) {
+ return -EAGAIN;
+ }
+#else
+ if (irq2dev_map[dev->irq] != NULL
+ || (irq2dev_map[dev->irq] = dev) == NULL
+ || dev->irq == 0
+ || request_irq(dev->irq, &epic_interrupt, 0, "SMC EPIC/100")) {
+ return -EAGAIN;
+ }
+#endif
+
+ MOD_INC_USE_COUNT;
+
+ epic_init_ring(dev);
+
+ /* This next line by Ken Yamaguchi.. ?? */
+ outl(0x8, ioaddr + 0x1c);
+
+ /* Pull the chip out of low-power mode, enable interrupts, and set for PCI read multiple. */
+ outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+
+ for (i = 0; i < 3; i++)
+ outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+
+ outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+ full_duplex = tp->full_duplex;
+
+ mii_reg5 = mii_read(ioaddr, tp->phys[0], 5);
+ if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
+ full_duplex = 1;
+ if (epic_debug > 1)
+ printk("%s: Setting %s-duplex based on MII xcvr %d"
+ " register read of %4.4x.\n", dev->name,
+ full_duplex ? "full" : "half", tp->phys[0],
+ mii_read(ioaddr, tp->phys[0], 5));
+ }
+
+ outl(full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ outl(virt_to_bus(tp->rx_ring), ioaddr + PRxCDAR);
+ outl(virt_to_bus(tp->tx_ring), ioaddr + PTxCDAR);
+
+ /* Start the chip's Rx process. */
+ set_rx_mode(dev);
+ outl(0x000A, ioaddr + COMMAND);
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /* Enable interrupts by setting the interrupt mask. */
+ outl(CntFull | TxUnderrun | TxDone
+ | RxError | RxOverflow | RxFull | RxHeader | RxDone,
+ ioaddr + INTMASK);
+
+ if (epic_debug > 1)
+ printk("%s: epic_open() ioaddr %4.4x IRQ %d status %4.4x %s-duplex.\n",
+ dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
+ full_duplex ? "full" : "half");
+
+ /* Set the timer to switch to check for link beat and perhaps switch
+ to an alternate media type. */
+ init_timer(&tp->timer);
+ tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
+ tp->timer.data = (unsigned long)dev;
+ tp->timer.function = &epic_timer; /* timer handler */
+ add_timer(&tp->timer);
+
+ return 0;
+}
+
+static void epic_timer(unsigned long data)
+{
+ struct device *dev = (struct device *)data;
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int next_tick = 0;
+
+ if (epic_debug > 3) {
+ printk("%s: Media selection tick, Tx status %8.8x.\n",
+ dev->name, inl(ioaddr + TxSTAT));
+ printk("%s: Other registers are IntMask %4.4x IntStatus %4.4x RxStatus"
+ " %4.4x.\n",
+ dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
+ inl(ioaddr + RxSTAT));
+ }
+
+ if (next_tick) {
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+ }
+}
+
+static void epic_tx_timeout(struct device *dev)
+{
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if (epic_debug > 0) {
+ printk("%s: Transmit timeout using MII device, Tx status %4.4x.\n",
+ dev->name, inw(ioaddr + TxSTAT));
+ if (epic_debug > 1) {
+ printk("%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
+ dev->name, tp->dirty_tx, tp->cur_tx);
+ }
+ }
+ /* Perhaps stop and restart the chip's Tx processes . */
+ /* Trigger a transmit demand. */
+ outl(0x0004, dev->base_addr + COMMAND);
+
+ dev->trans_start = jiffies;
+ tp->stats.tx_errors++;
+ return;
+}
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void
+epic_init_ring(struct device *dev)
+{
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int i;
+
+ tp->tx_full = 0;
+ tp->cur_rx = tp->cur_tx = 0;
+ tp->dirty_rx = tp->dirty_tx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ tp->rx_ring[i].status = 0x8000; /* Owned by Epic chip */
+ tp->rx_ring[i].buflength = PKT_BUF_SZ;
+ {
+ /* Note the receive buffer must be longword aligned.
+ dev_alloc_skb() provides 16 byte alignment. But do *not*
+ use skb_reserve() to align the IP header! */
+ struct sk_buff *skb;
+ skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+ tp->rx_skbuff[i] = skb;
+ if (skb == NULL)
+ break; /* Bad news! */
+ skb->dev = dev; /* Mark as being used by this device. */
+#if LINUX_VERSION_CODE > 0x10300
+ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
+ tp->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
+#else
+ tp->rx_ring[i].bufaddr = virt_to_bus(skb->data);
+#endif
+ }
+ tp->rx_ring[i].next = virt_to_bus(&tp->rx_ring[i+1]);
+ }
+ /* Mark the last entry as wrapping the ring. */
+ tp->rx_ring[i-1].next = virt_to_bus(&tp->rx_ring[0]);
+
+ /* The Tx buffer descriptor is filled in as needed, but we
+ do need to clear the ownership bit. */
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ tp->tx_skbuff[i] = 0;
+ tp->tx_ring[i].status = 0x0000;
+ tp->tx_ring[i].next = virt_to_bus(&tp->tx_ring[i+1]);
+ }
+ tp->tx_ring[i-1].next = virt_to_bus(&tp->tx_ring[0]);
+}
+
+static int
+epic_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int entry;
+ u32 flag;
+
+ /* 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 (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ if (jiffies - dev->trans_start < TX_TIMEOUT)
+ return 1;
+ epic_tx_timeout(dev);
+ return 1;
+ }
+
+ /* Caution: the write order is important here, set the base address
+ with the "ownership" bits last. */
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = tp->cur_tx % TX_RING_SIZE;
+
+ tp->tx_skbuff[entry] = skb;
+ tp->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
+ tp->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
+ tp->tx_ring[entry].buflength = skb->len;
+
+ if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+ flag = 0x10; /* No interrupt */
+ dev->tbusy = 0;
+ } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+ flag = 0x14; /* Tx-done intr. */
+ dev->tbusy = 0;
+ } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+ flag = 0x10; /* No Tx-done intr. */
+ dev->tbusy = 0;
+ } else {
+ /* Leave room for two additional entries. */
+ flag = 0x14; /* Tx-done intr. */
+ tp->tx_full = 1;
+ }
+
+ tp->tx_ring[entry].control = flag;
+ tp->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */
+ tp->cur_tx++;
+ /* Trigger an immediate transmit demand. */
+ outl(0x0004, dev->base_addr + COMMAND);
+
+ dev->trans_start = jiffies;
+ if (epic_debug > 4)
+ printk("%s: Queued Tx packet size %d to slot %d, "
+ "flag %2.2x Tx status %8.8x.\n",
+ dev->name, (int)skb->len, entry, flag,
+ inl(dev->base_addr + TxSTAT));
+
+ return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+ after the Tx thread. */
+static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+{
+#ifdef SA_SHIRQ
+ struct device *dev = (struct device *)dev_instance;
+#else
+ struct device *dev = (struct device *)(irq2dev_map[irq]);
+#endif
+ struct epic_private *lp;
+ int status, ioaddr, boguscnt = max_interrupt_work;
+
+ if (dev == NULL) {
+ printk ("epic_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ ioaddr = dev->base_addr;
+ lp = (struct epic_private *)dev->priv;
+ if (dev->interrupt)
+ printk("%s: Re-entering the interrupt handler.\n", dev->name);
+
+ dev->interrupt = 1;
+
+ do {
+ status = inl(ioaddr + INTSTAT);
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ outl(status & 0x00007fff, ioaddr + INTSTAT);
+
+ if (epic_debug > 4)
+ printk("%s: interrupt interrupt=%#8.8x new intstat=%#8.8x.\n",
+ dev->name, status, inl(ioaddr + INTSTAT));
+
+ if ((status & (RxDone | TxEmpty | TxDone)) == 0)
+ break;
+
+ if (status & RxDone) /* Rx interrupt */
+ epic_rx(dev);
+
+ if (status & (TxEmpty | TxDone)) {
+ int dirty_tx;
+
+ for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+ int entry = dirty_tx % TX_RING_SIZE;
+ int txstatus = lp->tx_ring[entry].status;
+
+ if (txstatus < 0)
+ break; /* It still hasn't been Txed */
+
+ if ( ! (txstatus & 0x0001)) {
+ /* There was an major error, log it. */
+#ifndef final_version
+ if (epic_debug > 1)
+ printk("%s: Transmit error, Tx status %8.8x.\n",
+ dev->name, txstatus);
+#endif
+ lp->stats.tx_errors++;
+ if (txstatus & 0x1050) lp->stats.tx_aborted_errors++;
+ if (txstatus & 0x0008) lp->stats.tx_carrier_errors++;
+ if (txstatus & 0x0040) lp->stats.tx_window_errors++;
+ if (txstatus & 0x0010) lp->stats.tx_fifo_errors++;
+#ifdef ETHER_STATS
+ if (txstatus & 0x1000) lp->stats.collisions16++;
+#endif
+ } else {
+#ifdef ETHER_STATS
+ if ((txstatus & 0x0002) != 0) lp->stats.tx_deferred++;
+#endif
+ lp->stats.collisions += (txstatus >> 8) & 15;
+ lp->stats.tx_packets++;
+ }
+
+ /* Free the original skb. */
+ dev_kfree_skb(lp->tx_skbuff[entry]);
+ lp->tx_skbuff[entry] = 0;
+ }
+
+#ifndef final_version
+ if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+ printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+ dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+ dirty_tx += TX_RING_SIZE;
+ }
+#endif
+
+ if (lp->tx_full && dev->tbusy
+ && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ /* The ring is no longer full, clear tbusy. */
+ lp->tx_full = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+
+ lp->dirty_tx = dirty_tx;
+ }
+
+ /* Check uncommon events all at once. */
+ if (status & (CntFull | TxUnderrun | RxOverflow)) {
+ /* Always update the error counts to avoid overhead later. */
+ lp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ lp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ lp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+
+ if (status & TxUnderrun) { /* Tx FIFO underflow. */
+ lp->stats.tx_fifo_errors++;
+ /* Restart the transmit process. */
+ outl(0x0080, ioaddr + COMMAND);
+ }
+ if (status & RxOverflow) { /* Missed a Rx frame. */
+ lp->stats.rx_errors++;
+ }
+ /* Clear all error sources. */
+ outl(status & 0x7f18, ioaddr + INTSTAT);
+ }
+ if (--boguscnt < 0) {
+ printk("%s: Too much work at interrupt, IntrStatus=0x%8.8x.\n",
+ dev->name, status);
+ /* Clear all interrupt sources. */
+ outl(0x0001ffff, ioaddr + INTSTAT);
+ break;
+ }
+ } while (1);
+
+ if (epic_debug > 3)
+ printk("%s: exiting interrupt, intr_status=%#4.4x.\n",
+ dev->name, inl(ioaddr + INTSTAT));
+
+ /* Code that should never be run! Perhaps remove after testing.. */
+ {
+ static int stopit = 10;
+ if (dev->start == 0 && --stopit < 0) {
+ printk("%s: Emergency stop, looping startup interrupt.\n",
+ dev->name);
+ FREE_IRQ(irq, dev);
+ }
+ }
+
+ dev->interrupt = 0;
+ return;
+}
+
+static int
+epic_rx(struct device *dev)
+{
+ struct epic_private *lp = (struct epic_private *)dev->priv;
+ int entry = lp->cur_rx % RX_RING_SIZE;
+
+ if (epic_debug > 4)
+ printk(" In epic_rx(), entry %d %8.8x.\n", entry,
+ lp->rx_ring[entry].status);
+ /* If we own the next entry, it's a new packet. Send it up. */
+ while (lp->rx_ring[entry].status >= 0) {
+ int status = lp->rx_ring[entry].status;
+
+ if (epic_debug > 4)
+ printk(" epic_rx() status was %8.8x.\n", status);
+ if (status & 0x2000) {
+ printk("%s: Oversized Ethernet frame spanned multiple buffers,"
+ " status %4.4x!\n", dev->name, status);
+ lp->stats.rx_length_errors++;
+ } else if (status & 0x0006) {
+ /* Rx Frame errors are counted in hardware. */
+ lp->stats.rx_errors++;
+ } else {
+ /* Malloc up new buffer, compatible with net-2e. */
+ /* Omit the four octet CRC from the length. */
+ short pkt_len = lp->rx_ring[entry].rxlength - 4;
+ struct sk_buff *skb;
+ int rx_in_place = 0;
+
+ /* Check if the packet is long enough to just accept without
+ copying to a properly sized skbuff. */
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+ char *temp;
+
+ /* Pass up the skb already on the Rx ring. */
+ skb = lp->rx_skbuff[entry];
+ temp = skb_put(skb, pkt_len);
+ if (bus_to_virt(lp->rx_ring[entry].bufaddr) != temp)
+ printk("%s: Warning -- the skbuff addresses do not match"
+ " in epic_rx: %p vs. %p / %p.\n", dev->name,
+ bus_to_virt(lp->rx_ring[entry].bufaddr),
+ skb->head, temp);
+ /* Get a fresh skbuff to replace the filled one. */
+ newskb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+ if (newskb) {
+ rx_in_place = 1;
+ lp->rx_skbuff[entry] = newskb;
+ newskb->dev = dev;
+#if LINUX_VERSION_CODE > 0x10300
+ /* Align IP on 16 byte boundaries */
+ skb_reserve(newskb, 2);
+ lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->tail);
+#else
+ lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->data);
+#endif
+ } else /* No memory, drop the packet. */
+ skb = 0;
+ } else
+ skb = DEV_ALLOC_SKB(pkt_len + 2);
+ if (skb == NULL) {
+ int i;
+ printk("%s: Memory squeeze, deferring packet.\n", dev->name);
+ /* Check that at least two ring entries are free.
+ If not, free one and mark stats->rx_dropped++. */
+ for (i = 0; i < RX_RING_SIZE; i++)
+ if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0)
+ break;
+
+ if (i > RX_RING_SIZE -2) {
+ lp->stats.rx_dropped++;
+ lp->rx_ring[entry].status = 0x8000;
+ lp->cur_rx++;
+ }
+ break;
+ }
+ skb->dev = dev;
+ if (! rx_in_place) {
+ skb_reserve(skb, 2); /* 16 byte align the data fields */
+ memcpy(skb_put(skb, pkt_len),
+ bus_to_virt(lp->rx_ring[entry].bufaddr), pkt_len);
+ }
+#if LINUX_VERSION_CODE > 0x10300
+ skb->protocol = eth_type_trans(skb, dev);
+#else
+ skb->len = pkt_len;
+#endif
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+ }
+
+ lp->rx_ring[entry].status = 0x8000;
+ entry = (++lp->cur_rx) % RX_RING_SIZE;
+ }
+
+ return 0;
+}
+
+static int
+epic_close(struct device *dev)
+{
+ int ioaddr = dev->base_addr;
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int i;
+
+ dev->start = 0;
+ dev->tbusy = 1;
+
+ if (epic_debug > 1)
+ printk("%s: Shutting down ethercard, status was %2.2x.\n",
+ dev->name, inl(ioaddr + INTSTAT));
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0x00000000, ioaddr + INTMASK);
+ /* Stop the chip's Tx and Rx DMA processes. */
+ outw(0x0061, ioaddr + COMMAND);
+
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+
+ del_timer(&tp->timer);
+
+#ifdef SA_SHIRQ
+ free_irq(dev->irq, dev);
+#else
+ free_irq(dev->irq);
+ irq2dev_map[dev->irq] = 0;
+#endif
+
+ /* Free all the skbuffs in the Rx queue. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ struct sk_buff *skb = tp->rx_skbuff[i];
+ tp->rx_skbuff[i] = 0;
+ tp->rx_ring[i].status = 0; /* Not owned by Epic chip. */
+ tp->rx_ring[i].buflength = 0;
+ tp->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
+ if (skb) {
+#if LINUX_VERSION_CODE < 0x20100
+ skb->free = 1;
+#endif
+ dev_kfree_skb(skb);
+ }
+ }
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ if (tp->tx_skbuff[i])
+ dev_kfree_skb(tp->tx_skbuff[i]);
+ tp->tx_skbuff[i] = 0;
+ }
+
+
+ /* Green! Leave the chip in low-power mode. */
+ outl(0x0008, ioaddr + GENCTL);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+static struct enet_statistics *
+epic_get_stats(struct device *dev)
+{
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if (dev->start) {
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ }
+
+ return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ Note that we only use exclusion around actually queueing the
+ new frame, not around filling tp->setup_frame. This is non-deterministic
+ when re-entered but still correct. */
+
+/* The little-endian AUTODIN II ethernet CRC calculation.
+ N.B. Do not use for bulk data, use a table-based routine instead.
+ This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline unsigned ether_crc_le(int length, unsigned char *data)
+{
+ unsigned int crc = 0xffffffff; /* Initial value. */
+ while(--length >= 0) {
+ unsigned char current_octet = *data++;
+ int bit;
+ for (bit = 8; --bit >= 0; current_octet >>= 1) {
+ if ((crc ^ current_octet) & 1) {
+ crc >>= 1;
+ crc ^= ethernet_polynomial_le;
+ } else
+ crc >>= 1;
+ }
+ }
+ return crc;
+}
+
+
+#ifdef NEW_MULTICAST
+static void set_rx_mode(struct device *dev)
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+{
+ int ioaddr = dev->base_addr;
+ struct epic_private *tp = (struct epic_private *)dev->priv;
+ unsigned char mc_filter[8]; /* Multicast hash filter */
+ int i;
+
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
+ outl(0x002C, ioaddr + RxCtrl);
+ /* Unconditionally log net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+ } else if ((dev->mc_count > 0) || (dev->flags & IFF_ALLMULTI)) {
+ /* There is apparently a chip bug, so the multicast filter
+ is never enabled. */
+ /* Too many to filter perfectly -- accept all multicasts. */
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+ outl(0x000C, ioaddr + RxCtrl);
+ } else if (dev->mc_count == 0) {
+ outl(0x0004, ioaddr + RxCtrl);
+ return;
+ } else { /* Never executed, for now. */
+ struct dev_mc_list *mclist;
+
+ memset(mc_filter, 0, sizeof(mc_filter));
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist = mclist->next)
+ set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
+ mc_filter);
+ }
+ /* ToDo: perhaps we need to stop the Tx and Rx process here? */
+ if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
+ for (i = 0; i < 4; i++)
+ outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
+ memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+ }
+ return;
+}
+
+#ifdef MODULE
+
+/* An additional parameter that may be passed in... */
+static int debug = -1;
+
+int
+init_module(void)
+{
+ int cards_found;
+
+ if (debug >= 0)
+ epic_debug = debug;
+
+ root_epic_dev = NULL;
+ cards_found = epic100_probe(0);
+
+ return cards_found ? 0 : -ENODEV;
+}
+
+void
+cleanup_module(void)
+{
+ struct device *next_dev;
+
+ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+ while (root_epic_dev) {
+ next_dev = ((struct epic_private *)root_epic_dev->priv)->next_module;
+ unregister_netdev(root_epic_dev);
+ release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
+ kfree(root_epic_dev);
+ root_epic_dev = next_dev;
+ }
+}
+
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c"
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
new file mode 100644
index 000000000..198ba1633
--- /dev/null
+++ b/drivers/net/hamradio/6pack.c
@@ -0,0 +1,1129 @@
+/*
+ * 6pack.c This module implements the 6pack protocol for kernel-based
+ * devices like TTY. It interfaces between a raw TTY and the
+ * kernel's AX.25 protocol layers.
+ *
+ * Version: @(#)6pack.c 0.3.0 04/07/98
+ *
+ * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ *
+ * Quite a lot of stuff "stolen" by Jörg Reuter from slip.c, written by
+ *
+ * Laurence Culhane, <loz@holmes.demon.co.uk>
+ * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <net/ax25.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/if_slip.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+/*
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+*/
+
+#include "6pack.h"
+
+typedef unsigned char byte;
+
+
+typedef struct sixpack_ctrl {
+ char if_name[8]; /* "sp0\0" .. "sp99999\0" */
+ struct sixpack ctrl; /* 6pack things */
+ struct device dev; /* the device */
+} sixpack_ctrl_t;
+static sixpack_ctrl_t **sixpack_ctrls = NULL;
+int sixpack_maxdev = SIXP_NRUNIT; /* Can be overridden with insmod! */
+
+static struct tty_ldisc sp_ldisc;
+
+static void sp_start_tx_timer(struct sixpack *);
+static void sp_xmit_on_air(unsigned long);
+static void resync_tnc(unsigned long);
+void sixpack_decode(struct sixpack *, unsigned char[], int);
+int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
+
+void decode_prio_command(byte, struct sixpack *);
+void decode_std_command(byte, struct sixpack *);
+void decode_data(byte, struct sixpack *);
+
+static int tnc_init(struct sixpack *);
+
+/* Find a free 6pack channel, and link in this `tty' line. */
+static inline struct sixpack *
+sp_alloc(void)
+{
+ sixpack_ctrl_t *spp = NULL;
+ int i;
+
+ if (sixpack_ctrls == NULL) return NULL; /* Master array missing ! */
+
+ for (i = 0; i < sixpack_maxdev; i++)
+ {
+ spp = sixpack_ctrls[i];
+
+ if (spp == NULL)
+ break;
+
+ if (!test_and_set_bit(SIXPF_INUSE, &spp->ctrl.flags))
+ break;
+ }
+
+ /* Too many devices... */
+ if (i >= sixpack_maxdev)
+ return NULL;
+
+ /* If no channels are available, allocate one */
+ if (!spp &&
+ (sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t),
+ GFP_KERNEL)) != NULL)
+ {
+ spp = sixpack_ctrls[i];
+ memset(spp, 0, sizeof(sixpack_ctrl_t));
+
+ /* Initialize channel control data */
+ set_bit(SIXPF_INUSE, &spp->ctrl.flags);
+ spp->ctrl.tty = NULL;
+ sprintf(spp->if_name, "sp%d", i);
+ spp->dev.name = spp->if_name;
+ spp->dev.base_addr = i;
+ spp->dev.priv = (void*)&(spp->ctrl);
+ spp->dev.next = NULL;
+ spp->dev.init = sixpack_init;
+ }
+
+ if (spp != NULL)
+ {
+ /* register device so that it can be ifconfig'ed */
+ /* sixpack_init() will be called as a side-effect */
+ /* SIDE-EFFECT WARNING: sixpack_init() CLEARS spp->ctrl ! */
+
+ if (register_netdev(&(spp->dev)) == 0)
+ {
+ set_bit(SIXPF_INUSE, &spp->ctrl.flags);
+ spp->ctrl.dev = &(spp->dev);
+ spp->dev.priv = (void*)&(spp->ctrl);
+
+ return (&(spp->ctrl));
+ } else {
+ clear_bit(SIXPF_INUSE,&(spp->ctrl.flags));
+ printk(KERN_WARNING "sp_alloc() - register_netdev() failure.\n");
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Free a 6pack channel. */
+static inline void
+sp_free(struct sixpack *sp)
+{
+ /* Free all 6pack frame buffers. */
+ if (sp->rbuff)
+ kfree(sp->rbuff);
+ sp->rbuff = NULL;
+ if (sp->xbuff) {
+ kfree(sp->xbuff);
+ }
+ sp->xbuff = NULL;
+
+ if (!test_and_clear_bit(SIXPF_INUSE, &sp->flags))
+ {
+ printk(KERN_WARNING "%s: sp_free for already free unit.\n", sp->dev->name);
+ }
+}
+
+
+/* Set the "sending" flag. */
+static inline void
+sp_lock(struct sixpack *sp)
+{
+ if (test_and_set_bit(0, (void *) &sp->dev->tbusy))
+ printk(KERN_WARNING "%s: trying to lock already locked device!\n", sp->dev->name);
+}
+
+
+/* Clear the "sending" flag. */
+static inline void
+sp_unlock(struct sixpack *sp)
+{
+ if (!test_and_clear_bit(0, (void *)&sp->dev->tbusy))
+ printk(KERN_WARNING "%s: trying to unlock already unlocked device!\n", sp->dev->name);
+}
+
+
+/* Send one completely decapsulated IP datagram to the IP layer. */
+
+/* This is the routine that sends the received data to the kernel AX.25.
+ 'cmd' is the KISS command. For AX.25 data, it is zero. */
+
+static void
+sp_bump(struct sixpack *sp, char cmd)
+{
+ struct sk_buff *skb;
+ int count;
+ unsigned char *ptr;
+
+ count = sp->rcount+1;
+
+ sp->rx_bytes+=count;
+
+ skb = dev_alloc_skb(count);
+ if (skb == NULL)
+ {
+ printk(KERN_DEBUG "%s: memory squeeze, dropping packet.\n", sp->dev->name);
+ sp->rx_dropped++;
+ return;
+ }
+
+ skb->dev = sp->dev;
+ ptr = skb_put(skb, count);
+ *ptr++ = cmd; /* KISS command */
+
+ memcpy(ptr, (sp->cooked_buf)+1, count);
+ skb->mac.raw=skb->data;
+ skb->protocol=htons(ETH_P_AX25);
+ netif_rx(skb);
+ sp->rx_packets++;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
+static void
+sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
+{
+ unsigned char *p;
+ int actual, count;
+
+ if (len > sp->mtu) /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
+ {
+ len = sp->mtu;
+ printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
+ sp->tx_dropped++;
+ sp_unlock(sp);
+ return;
+ }
+
+ p = icp;
+
+ if (p[0] > 5)
+ {
+ printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
+ sp_unlock(sp);
+ return;
+ }
+
+ if ((p[0] != 0) && (len > 2))
+ {
+ printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
+ sp_unlock(sp);
+ return;
+ }
+
+ if ((p[0] == 0) && (len < 15))
+ {
+ printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
+ sp_unlock(sp);
+ sp->tx_dropped++;
+ return;
+ }
+
+ count = encode_sixpack(p, (unsigned char *) sp->xbuff, len, sp->tx_delay);
+ sp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+
+ switch(p[0])
+ {
+ case 1: sp->tx_delay = p[1]; return;
+ case 2: sp->persistance = p[1]; return;
+ case 3: sp->slottime = p[1]; return;
+ case 4: /* ignored */ return;
+ case 5: sp->duplex = p[1]; return;
+ }
+
+ if (p[0] == 0) {
+ /* in case of fullduplex or DAMA operation, we don't take care
+ about the state of the DCD or of any timers, as the determination
+ of the correct time to send is the job of the AX.25 layer. We send
+ immediately after data has arrived. */
+ if (sp->duplex == 1){
+ sp->led_state = 0x70;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tx_enable = 1;
+ actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, count);
+ sp->xleft = count - actual;
+ sp->xhead = sp->xbuff + actual;
+ sp->led_state = 0x60;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ }
+ else {
+ sp->xleft = count;
+ sp->xhead = sp->xbuff;
+ sp->status2 = count;
+ if (sp->duplex == 0)
+ sp_start_tx_timer(sp);
+ }
+ }
+}
+
+/*
+ * Called by the TTY driver when there's room for more data. If we have
+ * more packets to send, we send them here.
+ */
+static void sixpack_write_wakeup(struct tty_struct *tty)
+{
+ int actual;
+ struct sixpack *sp = (struct sixpack *) tty->disc_data;
+
+ /* First make sure we're connected. */
+ if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start) {
+ return;
+ }
+ if (sp->xleft <= 0) {
+ /* Now serial buffer is almost free & we can start
+ * transmission of another packet */
+ sp->tx_packets++;
+ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ sp_unlock(sp);
+ sp->tx_enable = 0;
+ mark_bh(NET_BH);
+ return;
+ }
+
+ if (sp->tx_enable == 1) {
+ actual = tty->driver.write(tty, 0, sp->xhead, sp->xleft);
+ sp->xleft -= actual;
+ sp->xhead += actual;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Encapsulate an IP datagram and kick it into a TTY queue. */
+
+static int
+sp_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+ if (!dev->start)
+ {
+ printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
+ return 1;
+ }
+
+ if (dev->tbusy)
+ return 1;
+
+ /* We were not busy, so we are now... :-) */
+ if (skb != NULL) {
+ sp_lock(sp);
+ sp->tx_bytes+=skb->len; /*---2.1.x---*/
+ sp_encaps(sp, skb->data, skb->len);
+ dev_kfree_skb(skb);
+ }
+ return 0;
+}
+/* #endif */
+
+
+/* perform the persistence/slottime algorithm for CSMA access. If the persistence
+ check was successful, write the data to the serial driver. Note that in case
+ of DAMA operation, the data is not sent here. */
+
+static
+void sp_xmit_on_air(unsigned long channel)
+{
+ struct sixpack *sp = (struct sixpack *) channel;
+ int actual;
+ static unsigned char random;
+
+ random = random * 17 + 41;
+
+ if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistance)) {
+ sp->led_state = 0x70;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
+ sp->tx_enable = 1;
+ actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
+ sp->xleft -= actual;
+ sp->xhead += actual;
+ sp->led_state = 0x60;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
+ sp->status2 = 0;
+ } else
+ sp_start_tx_timer(sp);
+} /* sp_xmit */
+
+/* #if defined(CONFIG_6PACK) || defined(CONFIG_6PACK_MODULE) */
+
+/* Return the frame type ID */
+static int sp_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
+{
+#ifdef CONFIG_INET
+ if (type != htons(ETH_P_AX25))
+ return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+#endif
+ return 0;
+}
+
+
+static int sp_rebuild_header(struct sk_buff *skb)
+{
+#ifdef CONFIG_INET
+ return ax25_rebuild_header(skb);
+#else
+ return 0;
+#endif
+}
+
+/* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
+
+/* Open the low-level part of the 6pack channel. */
+static int
+sp_open(struct device *dev)
+{
+ struct sixpack *sp = (struct sixpack*)(dev->priv);
+ unsigned long len;
+
+ if (sp->tty == NULL)
+ return -ENODEV;
+
+ /*
+ * Allocate the 6pack frame buffers:
+ *
+ * rbuff Receive buffer.
+ * xbuff Transmit buffer.
+ * cbuff Temporary compression buffer.
+ */
+
+ /* !!! length of the buffers. MTU is IP MTU, not PACLEN!
+ */
+
+ len = dev->mtu * 2;
+
+ sp->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+ if (sp->rbuff == NULL)
+ return -ENOMEM;
+
+ sp->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+ if (sp->xbuff == NULL)
+ {
+ kfree(sp->rbuff);
+ return -ENOMEM;
+ }
+
+ sp->mtu = AX25_MTU + 73;
+ sp->buffsize = len;
+ sp->rcount = 0;
+ sp->rx_count = 0;
+ sp->rx_count_cooked = 0;
+ sp->xleft = 0;
+
+ sp->flags &= (1 << SIXPF_INUSE); /* Clear ESCAPE & ERROR flags */
+
+ sp->duplex = 0;
+ sp->tx_delay = SIXP_TXDELAY;
+ sp->persistance = SIXP_PERSIST;
+ sp->slottime = SIXP_SLOTTIME;
+ sp->led_state = 0x60;
+ sp->status = 1;
+ sp->status1 = 1;
+ sp->status2 = 0;
+ sp->tnc_ok = 0;
+ sp->tx_enable = 0;
+
+ dev->tbusy = 0;
+ dev->start = 1;
+
+ init_timer(&sp->tx_t);
+ init_timer(&sp->resync_t);
+ return 0;
+}
+
+
+/* Close the low-level part of the 6pack channel. */
+static int
+sp_close(struct device *dev)
+{
+ struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+ if (sp->tty == NULL) {
+ return -EBUSY;
+ }
+ sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ return 0;
+}
+
+static int
+sixpack_receive_room(struct tty_struct *tty)
+{
+ return 65536; /* We can handle an infinite amount of data. :-) */
+}
+
+/* !!! receive state machine */
+
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of 6pack data has been received, which can now be decapsulated
+ * and sent on to some IP layer for further processing.
+ */
+static void
+sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+{
+ unsigned char buf[512];
+ unsigned long flags;
+ int count1;
+
+ struct sixpack *sp = (struct sixpack *) tty->disc_data;
+
+ if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start || !count)
+ return;
+
+ save_flags(flags);
+ cli();
+ memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
+ restore_flags(flags);
+
+ /* Read the characters out of the buffer */
+
+ count1 = count;
+ while(count)
+ {
+ count--;
+ if (fp && *fp++)
+ {
+ if (!test_and_set_bit(SIXPF_ERROR, &sp->flags)) {
+ sp->rx_errors++;
+ }
+ continue;
+ }
+ }
+ sixpack_decode(sp, buf, count1);
+}
+
+/*
+ * Open the high-level part of the 6pack channel.
+ * This function is called by the TTY module when the
+ * 6pack line discipline is called for. Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free 6pcack channel...
+ */
+static int
+sixpack_open(struct tty_struct *tty)
+{
+ struct sixpack *sp = (struct sixpack *) tty->disc_data;
+ int err;
+
+ /* First make sure we're not already connected. */
+
+ if (sp && sp->magic == SIXPACK_MAGIC)
+ return -EEXIST;
+
+ /* OK. Find a free 6pack channel to use. */
+ if ((sp = sp_alloc()) == NULL)
+ return -ENFILE;
+ sp->tty = tty;
+ tty->disc_data = sp;
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+
+
+ /* Restore default settings */
+ sp->dev->type = ARPHRD_AX25;
+
+ /* Perform the low-level 6pack initialization. */
+ if ((err = sp_open(sp->dev)))
+ return err;
+
+ MOD_INC_USE_COUNT;
+
+ /* Done. We have linked the TTY line to a channel. */
+
+ tnc_init(sp);
+
+ return sp->dev->base_addr;
+}
+
+
+/*
+ * Close down a 6pack channel.
+ * This means flushing out any pending queues, and then restoring the
+ * TTY line discipline to what it was before it got hooked to 6pack
+ * (which usually is TTY again).
+ */
+static void
+sixpack_close(struct tty_struct *tty)
+{
+ struct sixpack *sp = (struct sixpack *) tty->disc_data;
+
+ /* First make sure we're connected. */
+ if (!sp || sp->magic != SIXPACK_MAGIC)
+ return;
+
+ rtnl_lock();
+ if (sp->dev->flags & IFF_UP)
+ (void) dev_close(sp->dev);
+
+ del_timer(&(sp->tx_t));
+ del_timer(&(sp->resync_t));
+
+ tty->disc_data = 0;
+ sp->tty = NULL;
+ /* VSV = very important to remove timers */
+
+ sp_free(sp);
+ unregister_netdev(sp->dev);
+ rtnl_unlock();
+ MOD_DEC_USE_COUNT;
+}
+
+
+static struct net_device_stats *
+sp_get_stats(struct device *dev)
+{
+ static struct net_device_stats stats;
+ struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+ memset(&stats, 0, sizeof(struct net_device_stats));
+
+ stats.rx_packets = sp->rx_packets;
+ stats.tx_packets = sp->tx_packets;
+ stats.rx_bytes = sp->rx_bytes;
+ stats.tx_bytes = sp->tx_bytes;
+ stats.rx_dropped = sp->rx_dropped;
+ stats.tx_dropped = sp->tx_dropped;
+ stats.tx_errors = sp->tx_errors;
+ stats.rx_errors = sp->rx_errors;
+ stats.rx_over_errors = sp->rx_over_errors;
+ return (&stats);
+}
+
+
+int
+sp_set_mac_address(struct device *dev, void *addr)
+{
+ int err;
+
+ err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN);
+ if (err) {
+ return err;
+ }
+
+ copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN); /* addr is an AX.25 shifted ASCII mac address */
+
+ return 0;
+}
+
+static int
+sp_set_dev_mac_address(struct device *dev, void *addr)
+{
+ struct sockaddr *sa=addr;
+ memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
+ return 0;
+}
+
+
+/* Perform I/O control on an active 6pack channel. */
+static int
+sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
+{
+ struct sixpack *sp = (struct sixpack *) tty->disc_data;
+ int err;
+ unsigned int tmp;
+
+ /* First make sure we're connected. */
+ if (!sp || sp->magic != SIXPACK_MAGIC) {
+ return -EINVAL;
+ }
+
+ switch(cmd) {
+ case SIOCGIFNAME:
+ err = verify_area(VERIFY_WRITE, arg, strlen(sp->dev->name) + 1);
+ if (err) {
+ return err;
+ }
+ copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1);
+ return 0;
+
+ case SIOCGIFENCAP:
+ err = verify_area(VERIFY_WRITE, arg, sizeof(int));
+ if (err) {
+ return err;
+ }
+ put_user(0, (int *)arg);
+ return 0;
+
+ case SIOCSIFENCAP:
+ err = verify_area(VERIFY_READ, arg, sizeof(int));
+ if (err) {
+ return err;
+ }
+ get_user(tmp,(int *)arg);
+
+ sp->mode = tmp;
+ sp->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
+ sp->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
+ sp->dev->type = ARPHRD_AX25;
+
+ return 0;
+
+ case SIOCSIFHWADDR:
+ return sp_set_mac_address(sp->dev, arg);
+
+ /* Allow stty to read, but not set, the serial port */
+ case TCGETS:
+ case TCGETA:
+ return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int sp_open_dev(struct device *dev)
+{
+ struct sixpack *sp = (struct sixpack*)(dev->priv);
+ if(sp->tty==NULL)
+ return -ENODEV;
+ return 0;
+}
+
+/* Initialize 6pack control device -- register 6pack line discipline */
+
+#ifdef MODULE
+static int sixpack_init_ctrl_dev(void)
+#else /* !MODULE */
+__initfunc sixpack_init_ctrl_dev(struct device *dummy)
+#endif /* !MODULE */
+{
+ int status;
+
+ if (sixpack_maxdev < 4) sixpack_maxdev = 4; /* Sanity */
+
+ printk(KERN_INFO "6pack: %s (dynamic channels, max=%d)\n",
+ SIXPACK_VERSION, sixpack_maxdev);
+
+ sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
+ if (sixpack_ctrls == NULL)
+ {
+ printk(KERN_WARNING "6pack: Can't allocate sixpack_ctrls[] array! Uaargh! (-> No 6pack available)\n");
+ return -ENOMEM;
+ }
+
+ /* Clear the pointer array, we allocate devices when we need them */
+ memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
+
+
+ /* Fill in our line protocol discipline, and register it */
+ memset(&sp_ldisc, 0, sizeof(sp_ldisc));
+ sp_ldisc.magic = TTY_LDISC_MAGIC;
+ sp_ldisc.name = "6pack";
+ sp_ldisc.flags = 0;
+ sp_ldisc.open = sixpack_open;
+ sp_ldisc.close = sixpack_close;
+ sp_ldisc.read = NULL;
+ sp_ldisc.write = NULL;
+ sp_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
+ unsigned int, unsigned long)) sixpack_ioctl;
+ sp_ldisc.poll = NULL;
+ sp_ldisc.receive_buf = sixpack_receive_buf;
+ sp_ldisc.receive_room = sixpack_receive_room;
+ sp_ldisc.write_wakeup = sixpack_write_wakeup;
+ if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) {
+ printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
+ }
+
+#ifdef MODULE
+ return status;
+#else
+ /* Return "not found", so that dev_init() will unlink
+ * the placeholder device entry for us.
+ */
+ return ENODEV;
+#endif
+}
+
+/* Initialize the 6pack driver. Called by DDI. */
+int
+sixpack_init(struct device *dev)
+{
+ struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+ static char ax25_bcast[AX25_ADDR_LEN] =
+ {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
+ static char ax25_test[AX25_ADDR_LEN] =
+ {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+
+ if (sp == NULL) /* Allocation failed ?? */
+ return -ENODEV;
+
+ /* Set up the "6pack Control Block". (And clear statistics) */
+
+ memset(sp, 0, sizeof (struct sixpack));
+ sp->magic = SIXPACK_MAGIC;
+ sp->dev = dev;
+
+ /* Finish setting up the DEVICE info. */
+ dev->mtu = SIXP_MTU;
+ dev->hard_start_xmit = sp_xmit;
+ dev->open = sp_open_dev;
+ dev->stop = sp_close;
+ dev->hard_header = sp_header;
+ dev->get_stats = sp_get_stats;
+ dev->set_mac_address = sp_set_dev_mac_address;
+ dev->hard_header_len = AX25_MAX_HEADER_LEN;
+ dev->addr_len = AX25_ADDR_LEN;
+ dev->type = ARPHRD_AX25;
+ dev->tx_queue_len = 10;
+ dev->rebuild_header = sp_rebuild_header;
+
+ memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); /* Only activated in AX.25 mode */
+ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); /* "" "" "" "" */
+
+ dev_init_buffers(dev);
+
+ /* New-style flags. */
+ dev->flags = 0;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+int
+init_module(void)
+{
+ return sixpack_init_ctrl_dev();
+}
+
+void
+cleanup_module(void)
+{
+ int i;
+
+ if (sixpack_ctrls != NULL)
+ {
+ for (i = 0; i < sixpack_maxdev; i++)
+ {
+ if (sixpack_ctrls[i])
+ {
+ /*
+ * VSV = if dev->start==0, then device
+ * unregistered while close proc.
+ */
+ if (sixpack_ctrls[i]->dev.start)
+ unregister_netdev(&(sixpack_ctrls[i]->dev));
+
+ kfree(sixpack_ctrls[i]);
+ sixpack_ctrls[i] = NULL;
+ }
+ }
+ kfree(sixpack_ctrls);
+ sixpack_ctrls = NULL;
+ }
+ if ((i = tty_register_ldisc(N_6PACK, NULL)))
+ {
+ printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
+ }
+}
+#endif /* MODULE */
+
+/* ----> 6pack timer interrupt handler and friends. <---- */
+static void
+sp_start_tx_timer(struct sixpack *sp)
+{
+ int when = sp->slottime;
+
+ del_timer(&(sp->tx_t));
+ sp->tx_t.data = (unsigned long) sp;
+ sp->tx_t.function = sp_xmit_on_air;
+ sp->tx_t.expires = jiffies + ((when+1)*HZ)/100;
+ add_timer(&(sp->tx_t));
+}
+
+
+/* encode an AX.25 packet into 6pack */
+
+int encode_sixpack(byte *tx_buf, byte *tx_buf_raw, int length, byte tx_delay)
+{
+ int count = 0;
+ byte checksum = 0, buf[400];
+ int raw_count = 0;
+
+ tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
+ tx_buf_raw[raw_count++] = SIXP_SEOF;
+
+ buf[0] = tx_delay;
+ for(count = 1; count < length; count++)
+ buf[count] = tx_buf[count];
+
+ for(count = 0; count < length; count++)
+ checksum += buf[count];
+ buf[length] = (byte)0xff - checksum;
+
+ for(count = 0; count <= length; count++) {
+ if((count % 3) == 0) {
+ tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
+ tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
+ }
+ else if((count % 3) == 1) {
+ tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
+ tx_buf_raw[raw_count] =
+ ((buf[count] >> 2) & 0x3c);
+ } else {
+ tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
+ tx_buf_raw[raw_count++] =
+ (buf[count] >> 2);
+ } /* else */
+ } /* for */
+ if ((length % 3) != 2)
+ raw_count++;
+ tx_buf_raw[raw_count++] = SIXP_SEOF;
+ return(raw_count);
+}
+
+
+/* decode a 6pack packet */
+
+void
+sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
+{
+ byte inbyte;
+ int count1;
+
+ for (count1 = 0; count1 < count; count1++) {
+ inbyte = pre_rbuff[count1];
+ if (inbyte == SIXP_FOUND_TNC) {
+ printk(KERN_INFO "6pack: TNC found.\n");
+ sp->tnc_ok = 1;
+ del_timer(&(sp->resync_t));
+ }
+ if((inbyte & SIXP_PRIO_CMD_MASK) != 0)
+ decode_prio_command(inbyte, sp);
+ else if((inbyte & SIXP_STD_CMD_MASK) != 0)
+ decode_std_command(inbyte, sp);
+ else {
+ if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
+ decode_data(inbyte, sp);
+ } /* else */
+ } /* for */
+}
+
+static int
+tnc_init(struct sixpack *sp)
+{
+ static byte inbyte;
+
+ inbyte = 0xe8;
+ sp->tty->driver.write(sp->tty, 0, &inbyte, 1);
+
+ del_timer(&(sp->resync_t));
+ sp->resync_t.data = (unsigned long) sp;
+ sp->resync_t.function = resync_tnc;
+ sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
+ add_timer(&(sp->resync_t));
+
+ return 0;
+}
+
+
+/* identify and execute a 6pack priority command byte */
+
+void decode_prio_command(byte cmd, struct sixpack *sp)
+{
+ byte channel;
+ int actual;
+
+ channel = cmd & SIXP_CHN_MASK;
+ if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */
+
+ /* RX and DCD flags can only be set in the same prio command,
+ if the DCD flag has been set without the RX flag in the previous
+ prio command. If DCD has not been set before, something in the
+ transmission has gone wrong. In this case, RX and DCD are
+ cleared in order to prevent the decode_data routine from
+ reading further data that might be corrupt. */
+
+ if (((sp->status & SIXP_DCD_MASK) == 0) &&
+ ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
+ if (sp->status != 1)
+ printk(KERN_DEBUG "6pack: protocol violation\n");
+ else
+ sp->status = 0;
+ cmd &= !SIXP_RX_DCD_MASK;
+ }
+ sp->status = cmd & SIXP_PRIO_DATA_MASK;
+ } /* if */
+ else { /* output watchdog char if idle */
+ if ((sp->status2 != 0) && (sp->duplex == 1)) {
+ sp->led_state = 0x70;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tx_enable = 1;
+ actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
+ sp->xleft -= actual;
+ sp->xhead += actual;
+ sp->led_state = 0x60;
+ sp->status2 = 0;
+
+ } /* if */
+ } /* else */
+
+ /* needed to trigger the TNC watchdog */
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+
+ /* if the state byte has been received, the TNC is present,
+ so the resync timer can be reset. */
+
+ if (sp->tnc_ok == 1) {
+ del_timer(&(sp->resync_t));
+ sp->resync_t.data = (unsigned long) sp;
+ sp->resync_t.function = resync_tnc;
+ sp->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
+ add_timer(&(sp->resync_t));
+ }
+
+ sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
+}
+
+/* try to resync the TNC. Called by the resync timer defined in
+ decode_prio_command */
+
+static void
+resync_tnc(unsigned long channel)
+{
+ static char resync_cmd = 0xe8;
+ struct sixpack *sp = (struct sixpack *) channel;
+
+ printk(KERN_INFO "6pack: resyncing TNC\n");
+
+ /* clear any data that might have been received */
+
+ sp->rx_count = 0;
+ sp->rx_count_cooked = 0;
+
+ /* reset state machine */
+
+ sp->status = 1;
+ sp->status1 = 1;
+ sp->status2 = 0;
+ sp->tnc_ok = 0;
+
+ /* resync the TNC */
+
+ sp->led_state = 0x60;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ sp->tty->driver.write(sp->tty, 0, &resync_cmd, 1);
+
+
+ /* Start resync timer again -- the TNC might be still absent */
+
+ del_timer(&(sp->resync_t));
+ sp->resync_t.data = (unsigned long) sp;
+ sp->resync_t.function = resync_tnc;
+ sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
+ add_timer(&(sp->resync_t));
+}
+
+
+
+/* identify and execute a standard 6pack command byte */
+
+void decode_std_command(byte cmd, struct sixpack *sp)
+{
+ byte checksum = 0, rest = 0, channel;
+ short i;
+
+ channel = cmd & SIXP_CHN_MASK;
+ switch(cmd & SIXP_CMD_MASK) { /* normal command */
+ case SIXP_SEOF:
+ if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
+ if ((sp->status & SIXP_RX_DCD_MASK) ==
+ SIXP_RX_DCD_MASK) {
+ sp->led_state = 0x68;
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ } /* if */
+ } else {
+ sp->led_state = 0x60;
+ /* fill trailing bytes with zeroes */
+ sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+ rest = sp->rx_count;
+ if (rest != 0)
+ for(i=rest; i<=3; i++)
+ decode_data(0, sp);
+ if (rest == 2)
+ sp->rx_count_cooked -= 2;
+ else if (rest == 3)
+ sp->rx_count_cooked -= 1;
+ for (i=0; i<sp->rx_count_cooked; i++)
+ checksum+=sp->cooked_buf[i];
+ if (checksum != SIXP_CHKSUM) {
+ printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
+ } else {
+ sp->rcount = sp->rx_count_cooked-2;
+ sp_bump(sp, 0);
+ } /* else */
+ sp->rx_count_cooked = 0;
+ } /* else */
+ break;
+ case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
+ break;
+ case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
+ break;
+ case SIXP_RX_BUF_OVL:
+ printk(KERN_DEBUG "6pack: RX buffer overflow\n");
+ } /* switch */
+} /* function */
+
+/* decode 4 sixpack-encoded bytes into 3 data bytes */
+
+void decode_data(byte inbyte, struct sixpack *sp)
+{
+
+ unsigned char *buf;
+
+ if (sp->rx_count != 3)
+ sp->raw_buf[sp->rx_count++] = inbyte;
+ else {
+ buf = sp->raw_buf;
+ sp->cooked_buf[sp->rx_count_cooked++] =
+ buf[0] | ((buf[1] << 2) & 0xc0);
+ sp->cooked_buf[sp->rx_count_cooked++] =
+ (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
+ sp->cooked_buf[sp->rx_count_cooked++] =
+ (buf[2] & 0x03) | (inbyte << 2);
+ sp->rx_count = 0;
+ }
+}
diff --git a/drivers/net/hamradio/6pack.h b/drivers/net/hamradio/6pack.h
new file mode 100644
index 000000000..a5fe532f3
--- /dev/null
+++ b/drivers/net/hamradio/6pack.h
@@ -0,0 +1,135 @@
+/*
+ * 6pack.h Define the 6pack device driver interface and constants.
+ *
+ * NOTE: THIS FILE WILL BE MOVED TO THE LINUX INCLUDE DIRECTORY
+ * AS SOON AS POSSIBLE!
+ *
+ * Version: @(#)6pack.h 0.3.0 04/07/98
+ *
+ * Fixes:
+ *
+ * Author: Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ *
+ * This file is derived from slip.h, written by
+ * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ */
+
+#ifndef _LINUX_6PACK_H
+#define _LINUX_6PACK_H
+
+#define SIXPACK_VERSION "Revision: 0.3.0"
+
+#ifdef __KERNEL__
+
+/* sixpack priority commands */
+#define SIXP_SEOF 0x40 /* start and end of a 6pack frame */
+#define SIXP_TX_URUN 0x48 /* transmit overrun */
+#define SIXP_RX_ORUN 0x50 /* receive overrun */
+#define SIXP_RX_BUF_OVL 0x58 /* receive buffer overflow */
+
+#define SIXP_CHKSUM 0xFF /* valid checksum of a 6pack frame */
+
+/* masks to get certain bits out of the status bytes sent by the TNC */
+
+#define SIXP_CMD_MASK 0xC0
+#define SIXP_CHN_MASK 0x07
+#define SIXP_PRIO_CMD_MASK 0x80
+#define SIXP_STD_CMD_MASK 0x40
+#define SIXP_PRIO_DATA_MASK 0x38
+#define SIXP_TX_MASK 0x20
+#define SIXP_RX_MASK 0x10
+#define SIXP_RX_DCD_MASK 0x18
+#define SIXP_LEDS_ON 0x78
+#define SIXP_LEDS_OFF 0x60
+#define SIXP_CON 0x08
+#define SIXP_STA 0x10
+
+#define SIXP_FOUND_TNC 0xe9
+#define SIXP_CON_ON 0x68
+#define SIXP_DCD_MASK 0x08
+#define SIXP_DAMA_OFF 0
+
+/* default level 2 parameters */
+#define SIXP_TXDELAY 25 /* in 10 ms */
+#define SIXP_PERSIST 50 /* in 256ths */
+#define SIXP_SLOTTIME 10 /* in 10 ms */
+#define SIXP_INIT_RESYNC_TIMEOUT 150 /* in 10 ms */
+#define SIXP_RESYNC_TIMEOUT 500 /* in 10 ms */
+
+/* 6pack configuration. */
+#define SIXP_NRUNIT 256 /* MAX number of 6pack channels */
+#define SIXP_MTU 256 /* Default MTU */
+
+enum sixpack_flags {
+ SIXPF_INUSE, /* Channel in use */
+ SIXPF_ERROR, /* Parity, etc. error */
+};
+
+struct sixpack {
+ int magic;
+
+ /* Various fields. */
+ struct tty_struct *tty; /* ptr to TTY structure */
+ struct device *dev; /* easy for intr handling */
+
+ /* These are pointers to the malloc()ed frame buffers. */
+ unsigned char *rbuff; /* receiver buffer */
+ int rcount; /* received chars counter */
+ unsigned char *xbuff; /* transmitter buffer */
+ unsigned char *xhead; /* pointer to next byte to XMIT */
+ int xleft; /* bytes left in XMIT queue */
+
+ unsigned char raw_buf[4];
+ unsigned char cooked_buf[400];
+
+ unsigned int rx_count;
+ unsigned int rx_count_cooked;
+
+ /* 6pack interface statistics. */
+ unsigned long rx_packets; /* inbound frames counter */
+ unsigned long tx_packets; /* outbound frames counter */
+ unsigned long rx_bytes; /* inbound bytes counter */
+ unsigned long tx_bytes; /* outboud bytes counter */
+ unsigned long rx_errors; /* Parity, etc. errors */
+ unsigned long tx_errors; /* Planned stuff */
+ unsigned long rx_dropped; /* No memory for skb */
+ unsigned long tx_dropped; /* When MTU change */
+ unsigned long rx_over_errors; /* Frame bigger then 6pack buf. */
+
+ /* Detailed 6pack statistics. */
+
+ int mtu; /* Our mtu (to spot changes!) */
+ int buffsize; /* Max buffers sizes */
+
+ unsigned char flags; /* Flag values/ mode etc */
+ unsigned char mode; /* 6pack mode */
+
+/* 6pack stuff */
+
+ unsigned char tx_delay;
+ unsigned char persistance;
+ unsigned char slottime;
+ unsigned char duplex;
+ unsigned char led_state;
+ unsigned char status;
+ unsigned char status1;
+ unsigned char status2;
+ unsigned char tx_enable;
+ unsigned char tnc_ok;
+
+/* unsigned char retval; */
+
+ struct timer_list tx_t;
+ struct timer_list resync_t;
+}; /* struct sixpack */
+
+
+/* should later be moved to include/net/ax25.h */
+#define AX25_6PACK_HEADER_LEN 0
+#define SIXPACK_MAGIC 0x5304
+
+extern int sixpack_init(struct device *dev);
+
+#endif
+
+#endif /* _LINUX_6PACK.H */
diff --git a/drivers/net/hamradio/Config.in b/drivers/net/hamradio/Config.in
index c0719608a..29e182fe9 100644
--- a/drivers/net/hamradio/Config.in
+++ b/drivers/net/hamradio/Config.in
@@ -1,7 +1,7 @@
comment 'AX.25 network device drivers'
dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
-# dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
+dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
dep_tristate 'BPQ Ethernet driver' CONFIG_BPQETHER $CONFIG_AX25
dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
diff --git a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefile
index c247cee79..07e2aade5 100644
--- a/drivers/net/hamradio/Makefile
+++ b/drivers/net/hamradio/Makefile
@@ -45,6 +45,14 @@ else
endif
endif
+ifeq ($(CONFIG_6PACK),y)
+L_OBJS += 6pack.o
+else
+ ifeq ($(CONFIG_6PACK),m)
+ M_OBJS += 6pack.o
+ endif
+endif
+
ifeq ($(CONFIG_PI),y)
L_OBJS += pi2.o
else
diff --git a/drivers/net/hamradio/soundmodem/gentbl.c b/drivers/net/hamradio/soundmodem/gentbl.c
index 3f507d248..e67733831 100644
--- a/drivers/net/hamradio/soundmodem/gentbl.c
+++ b/drivers/net/hamradio/soundmodem/gentbl.c
@@ -681,7 +681,7 @@ int main(int argc, char *argv[])
gentbl_costab(f, 6);
gentbl_afsk2400(f, 7372800);
fclose(f);
- return(0);
+ exit(0);
}
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 0f1bdd3c7..bd97a51b3 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2,7 +2,7 @@
** hp100.c
** HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters
**
-** $Id: hp100.c,v 1.56 1998/03/04 15:23:59 perex Exp perex $
+** $Id: hp100.c,v 1.57 1998/04/10 16:27:23 perex Exp perex $
**
** Based on the HP100 driver written by Jaroslav Kysela <perex@jcu.cz>
** Extended for new busmaster capable chipsets by
@@ -31,10 +31,23 @@
** - some updates for EISA version of card
**
**
-** This source/code is public free; you can distribute it and/or modify
-** it under terms of the GNU General Public License (published by the
-** Free Software Foundation) either version two of this License, or any
-** later version.
+** This code is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This code is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**
+** 1.56 -> 1.57
+** - updates for new PCI interface for 2.1 kernels
**
** 1.55 -> 1.56
** - removed printk in misc. interrupt and update statistics to allow
@@ -83,7 +96,6 @@
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <asm/bitops.h>
#include <asm/io.h>
@@ -95,13 +107,15 @@
#include <linux/config.h> /* for CONFIG_PCI */
#include <linux/delay.h>
-#if LINUX_VERSION_CODE < 0x020100
+#if LINUX_VERSION_CODE >= 0x020100
+#define LINUX_2_1
+typedef struct net_device_stats hp100_stats_t;
+EXPORT_NO_SYMBOLS;
+#else
+#include <linux/bios32.h>
#define ioremap vremap
#define iounmap vfree
typedef struct enet_statistics hp100_stats_t;
-#else
-#define LINUX_2_1
-typedef struct net_device_stats hp100_stats_t;
#endif
#ifndef __initfunc
@@ -136,14 +150,14 @@ typedef struct net_device_stats hp100_stats_t;
#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005
#endif
-#define HP100_REGION_SIZE 0x20 /* for ioports */
+#define HP100_REGION_SIZE 0x20 /* for ioports */
-#define HP100_MAX_PACKET_SIZE (1536+4)
-#define HP100_MIN_PACKET_SIZE 60
+#define HP100_MAX_PACKET_SIZE (1536+4)
+#define HP100_MIN_PACKET_SIZE 60
#ifndef HP100_DEFAULT_RX_RATIO
/* default - 75% onboard memory on the card are used for RX packets */
-#define HP100_DEFAULT_RX_RATIO 75
+#define HP100_DEFAULT_RX_RATIO 75
#endif
#ifndef HP100_DEFAULT_PRIORITY_TX
@@ -176,8 +190,12 @@ struct hp100_private {
u_short priority_tx; /* != 0 - priority tx */
u_short mode; /* PIO, Shared Mem or Busmaster */
u_char bus;
+#ifndef LINUX_2_1
u_char pci_bus;
u_char pci_device_fn;
+#else
+ struct pci_dev *pci_dev;
+#endif
short mem_mapped; /* memory mapped access */
u_int *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */
u_int *mem_ptr_phys; /* physical memory mapped area */
@@ -282,7 +300,11 @@ MODULE_PARM( hp100_mode, "1i" );
* prototypes
*/
-static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn );
+#ifdef LINUX_2_1
+static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev );
+#else
+static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn );
+#endif
static int hp100_open( struct device *dev );
static int hp100_close( struct device *dev );
static int hp100_start_xmit( struct sk_buff *skb, struct device *dev );
@@ -342,12 +364,24 @@ __initfunc(int hp100_probe( struct device *dev ))
{
if ( check_region( base_addr, HP100_REGION_SIZE ) ) return -EINVAL;
if ( base_addr < 0x400 )
+#ifdef LINUX_2_1
+ return hp100_probe1( dev, base_addr, HP100_BUS_ISA, NULL );
+#else
return hp100_probe1( dev, base_addr, HP100_BUS_ISA, 0, 0 );
+#endif
if ( EISA_bus && base_addr >= 0x1c38 && ( (base_addr - 0x1c38) & 0x3ff ) == 0 )
+#ifdef LINUX_2_1
+ return hp100_probe1( dev, base_addr, HP100_BUS_EISA, NULL );
+#else
return hp100_probe1( dev, base_addr, HP100_BUS_EISA, 0, 0 );
+#endif
#ifdef CONFIG_PCI
+#ifdef LINUX_2_1
+ printk( "hp100: %s: You must specify card # in i/o address parameter for PCI bus...", dev->name );
+#else
printk( "hp100: %s: You may specify card # in i/o address parameter for PCI bus...", dev->name );
return hp100_probe1( dev, base_addr, HP100_BUS_PCI, 0, 0 );
+#endif
#else
return -ENODEV;
#endif
@@ -366,10 +400,51 @@ __initfunc(int hp100_probe( struct device *dev ))
if ( pcibios_present() )
{
int pci_index;
+#ifdef LINUX_2_1
+ struct pci_dev *pci_dev = NULL;
+ int pci_id_index;
+ u_short pci_command;
+#endif
#ifdef HP100_DEBUG_PCI
printk( "hp100: %s: PCI BIOS is present, checking for devices..\n", dev->name );
#endif
+#ifdef LINUX_2_1
+ pci_index = 0;
+ for ( pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE; pci_id_index++ ) {
+ while ( (pci_dev = pci_find_device( hp100_pci_ids[ pci_id_index ].vendor,
+ hp100_pci_ids[ pci_id_index ].device,
+ pci_dev )) != NULL ) {
+ if ( pci_index < (pci_start_index & 7) ) {
+ pci_index++;
+ continue;
+ }
+ /* found... */
+ ioaddr = pci_dev -> base_address[ 0 ] & ~3;
+ if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
+ pci_read_config_word( pci_dev, PCI_COMMAND, &pci_command );
+ if ( !( pci_command & PCI_COMMAND_IO ) ) {
+#ifdef HP100_DEBUG
+ printk( "hp100: %s: PCI I/O Bit has not been set. Setting...\n", dev->name );
+#endif
+ pci_command |= PCI_COMMAND_IO;
+ pci_write_config_word( pci_dev, PCI_COMMAND, pci_command );
+ }
+ if ( !( pci_command & PCI_COMMAND_MASTER ) ) {
+#ifdef HP100_DEBUG
+ printk( "hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name );
+#endif
+ pci_command |= PCI_COMMAND_MASTER;
+ pci_write_config_word( pci_dev, PCI_COMMAND, pci_command );
+ }
+#ifdef HP100_DEBUG
+ printk( "hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr );
+#endif
+ if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI, pci_dev ) == 0 )
+ return 0;
+ }
+ }
+#else /* old PCI interface */
for ( pci_index = pci_start_index & 7; pci_index < 8; pci_index++ )
{
u_char pci_bus, pci_device_fn;
@@ -417,6 +492,7 @@ __initfunc(int hp100_probe( struct device *dev ))
if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI, pci_bus, pci_device_fn ) == 0 )
return 0;
}
+#endif
}
if ( pci_start_index > 0 ) return -ENODEV;
#endif /* CONFIG_PCI */
@@ -425,21 +501,33 @@ __initfunc(int hp100_probe( struct device *dev ))
for ( ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400 )
{
if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
+#ifdef LINUX_2_1
+ if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA, NULL ) == 0 ) return 0;
+#else
if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA, 0, 0 ) == 0 ) return 0;
+#endif
}
/* Third Probe all ISA possible port regions */
for ( ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20 )
{
if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
+#ifdef LINUX_2_1
+ if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA, NULL ) == 0 ) return 0;
+#else
if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA, 0, 0 ) == 0 ) return 0;
+#endif
}
return -ENODEV;
}
+#ifdef LINUX_2_1
+__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev ))
+#else
__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn ))
+#endif
{
int i;
@@ -703,15 +791,19 @@ __initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus,
/* Initialise the "private" data structure for this card. */
if ( (dev->priv=kmalloc(sizeof(struct hp100_private), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset( dev->priv, 0, sizeof(struct hp100_private) );
lp = (struct hp100_private *)dev->priv;
+ memset( lp, 0, sizeof( struct hp100_private ) );
lp->id = eid;
lp->chip = chip;
lp->mode = local_mode;
- lp->pci_bus = pci_bus;
lp->bus = bus;
+#ifdef LINUX_2_1
+ lp->pci_dev = pci_dev;
+#else
+ lp->pci_bus = pci_bus;
lp->pci_device_fn = pci_device_fn;
+#endif
lp->priority_tx = hp100_priority_tx;
lp->rx_ratio = hp100_rx_ratio;
lp->mem_ptr_phys = mem_ptr_phys;
@@ -743,10 +835,18 @@ __initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus,
dev->set_multicast_list = &hp100_set_multicast_list;
/* Ask the card for which IRQ line it is configured */
- hp100_page( HW_MAP );
- dev->irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQMASK;
- if ( dev->irq == 2 )
- dev->irq = 9;
+#ifdef LINUX_2_1
+ if ( bus == HP100_BUS_PCI ) {
+ dev->irq = pci_dev->irq;
+ } else {
+#endif
+ hp100_page( HW_MAP );
+ dev->irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQMASK;
+ if ( dev->irq == 2 )
+ dev->irq = 9;
+#ifdef LINUX_2_1
+ }
+#endif
if(lp->mode==1) /* busmaster */
dev->dma=4;
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 423b4a7ac..367654ea3 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -45,7 +45,6 @@ static const char *version = "lance.c:v1.09 Aug 20 1996 dplatt@3do.com, becker@c
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
@@ -285,7 +284,7 @@ static struct lance_chip_type {
enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6};
/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned char pci_irq_line = 0;
+static unsigned int pci_irq_line = 0;
/* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers.
Assume yes until we know the memory size. */
@@ -317,36 +316,26 @@ __initfunc(int lance_init(void))
lance_need_isa_bounce_buffers = 0;
#if defined(CONFIG_PCI) && !defined(CONFIG_PCNET32)
- if (pcibios_present()) {
- int pci_index;
+ if (pci_present()) {
+ struct pci_dev *pdev = NULL;
if (lance_debug > 1)
- printk("lance.c: PCI bios is present, checking for devices...\n");
- for (pci_index = 0; pci_index < 8; pci_index++) {
+ printk("lance.c: PCI is present, checking for devices...\n");
+ while (pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev)) {
unsigned char pci_bus, pci_device_fn;
unsigned int pci_ioaddr;
unsigned short pci_command;
- if (pcibios_find_device (PCI_VENDOR_ID_AMD,
- PCI_DEVICE_ID_AMD_LANCE, pci_index,
- &pci_bus, &pci_device_fn) != 0)
- break;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
/* PCI Spec 2.1 states that it is either the driver or PCI card's
* responsibility to set the PCI Master Enable Bit if needed.
* (From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
*/
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
if ( ! (pci_command & PCI_COMMAND_MASTER)) {
printk("PCI Master Bit has not been set. Setting...\n");
pci_command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, pci_command);
+ pci_write_config_word(pdev, PCI_COMMAND, pci_command);
}
printk("Found PCnet/PCI at %#x, irq %d.\n",
pci_ioaddr, pci_irq_line);
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index cf1e9e903..ea836aaa0 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -13,6 +13,7 @@
#include <asm/prom.h>
#include <asm/dbdma.h>
#include <asm/io.h>
+#include <asm/pgtable.h>
#include "mace.h"
#define N_RX_RING 8
@@ -117,21 +118,22 @@ mace_probe(struct device *dev)
mp = (struct mace_data *) dev->priv;
dev->base_addr = maces->addrs[0].address;
- mp->mace = (volatile struct mace *) maces->addrs[0].address;
- dev->irq = maces->intrs[0];
+ mp->mace = (volatile struct mace *)
+ ioremap(maces->addrs[0].address, 0x1000);
+ dev->irq = maces->intrs[0].line;
if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
return -EAGAIN;
}
- if (request_irq(maces->intrs[1], mace_txdma_intr, 0, "MACE-txdma",
+ if (request_irq(maces->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
dev)) {
- printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[1]);
+ printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[1].line);
return -EAGAIN;
}
- if (request_irq(maces->intrs[2], mace_rxdma_intr, 0, "MACE-rxdma",
+ if (request_irq(maces->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
dev)) {
- printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[2]);
+ printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[2].line);
return -EAGAIN;
}
@@ -155,10 +157,12 @@ mace_probe(struct device *dev)
mp = (struct mace_data *) dev->priv;
mp->maccc = ENXMT | ENRCV;
- mp->tx_dma = (volatile struct dbdma_regs *) maces->addrs[1].address;
- mp->tx_dma_intr = maces->intrs[1];
- mp->rx_dma = (volatile struct dbdma_regs *) maces->addrs[2].address;
- mp->rx_dma_intr = maces->intrs[2];
+ mp->tx_dma = (volatile struct dbdma_regs *)
+ ioremap(maces->addrs[1].address, 0x1000);
+ mp->tx_dma_intr = maces->intrs[1].line;
+ mp->rx_dma = (volatile struct dbdma_regs *)
+ ioremap(maces->addrs[2].address, 0x1000);
+ mp->rx_dma_intr = maces->intrs[2].line;
mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1);
mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1;
@@ -169,8 +173,6 @@ mace_probe(struct device *dev)
init_timer(&mp->tx_timeout);
mp->timeout_active = 0;
- mace_reset(dev);
-
dev->open = mace_open;
dev->stop = mace_close;
dev->hard_start_xmit = mace_xmit_start;
@@ -260,6 +262,9 @@ static int mace_open(struct device *dev)
struct sk_buff *skb;
unsigned char *data;
+ /* reset the chip */
+ mace_reset(dev);
+
/* initialize list of sk_buffs for receiving and set up recv dma */
memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd));
cp = mp->rx_cmds;
@@ -410,6 +415,10 @@ static int mace_xmit_start(struct sk_buff *skb, struct device *dev)
++mp->tx_active;
mace_set_timeout(dev);
}
+ if (++next >= N_TX_RING)
+ next = 0;
+ if (next == mp->tx_empty)
+ dev->tbusy = 1;
restore_flags(flags);
return 0;
@@ -520,6 +529,8 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
i = mp->tx_empty;
while (mb->pr & XMTSV) {
+ del_timer(&mp->tx_timeout);
+ mp->timeout_active = 0;
/*
* Clear any interrupt indication associated with this status
* word. This appears to unlatch any error indication from
@@ -533,8 +544,6 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
eieio();
mp->tx_bad_runt = 0;
mb->xmtfc = AUTO_PAD_XMIT;
- del_timer(&mp->tx_timeout);
- mp->timeout_active = 0;
continue;
}
dstat = ld_le32(&td->status);
@@ -562,7 +571,8 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
fs = mb->xmtfs;
if ((fs & XMTSV) == 0) {
- printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n", fs, xcount, dstat);
+ printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n",
+ fs, xcount, dstat);
}
cp = mp->tx_cmds + NCMDS_TX * i;
stat = ld_le16(&cp->xfer_status);
@@ -571,6 +581,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* Check whether there were in fact 2 bytes written to
* the transmit FIFO.
*/
+ udelay(1);
x = (mb->fifofc >> XMTFC_SH) & XMTFC_MASK;
if (x != 0) {
/* there were two bytes with an end-of-packet indication */
@@ -579,17 +590,21 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} else {
/*
* Either there weren't the two bytes buffered up, or they
- * didn't have an end-of-packet indication. Maybe we ought
- * to flush the transmit FIFO just in case (by setting the
+ * didn't have an end-of-packet indication.
+ * We flush the transmit FIFO just in case (by setting the
* XMTFWU bit with the transmitter disabled).
*/
- mb->xmtfc = AUTO_PAD_XMIT;
- eieio();
+ out_8(&mb->maccc, mb->maccc & ~ENXMT);
+ out_8(&mb->fifocc, mb->fifocc | XMTFWU);
+ udelay(1);
+ out_8(&mb->maccc, mb->maccc | ENXMT);
+ out_8(&mb->xmtfc, AUTO_PAD_XMIT);
}
}
/* dma should have finished */
if (i == mp->tx_fill) {
- printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n", fs, xcount, dstat);
+ printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n",
+ fs, xcount, dstat);
continue;
}
/* Update stats */
@@ -607,11 +622,9 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
i = 0;
mace_last_fs = fs;
mace_last_xcount = xcount;
- del_timer(&mp->tx_timeout);
- mp->timeout_active = 0;
}
- if (i != mp->tx_empty && mp->tx_fullup) {
+ if (i != mp->tx_empty) {
mp->tx_fullup = 0;
dev->tbusy = 0;
mark_bh(NET_BH);
@@ -656,9 +669,6 @@ static void mace_tx_timeout(unsigned long data)
mace_handle_misc_intrs(mp, mb->ir);
cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty;
- printk(KERN_DEBUG "mace: tx dmastat=%x %x bad_runt=%d pr=%x fs=%x fc=%x\n",
- ld_le32(&td->status), ld_le16(&cp->xfer_status), mp->tx_bad_runt,
- mb->pr, mb->xmtfs, mb->fifofc);
/* turn off both tx and rx and reset the chip */
mb->maccc = 0;
@@ -685,11 +695,9 @@ static void mace_tx_timeout(unsigned long data)
i = 0;
mp->tx_empty = i;
}
- if (mp->tx_fullup) {
- mp->tx_fullup = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
+ mp->tx_fullup = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
if (i != mp->tx_fill) {
cp = mp->tx_cmds + NCMDS_TX * i;
out_le16(&cp->xfer_status, 0);
diff --git a/drivers/net/mace.h b/drivers/net/mace.h
index a397c83b4..30b7ec0ce 100644
--- a/drivers/net/mace.h
+++ b/drivers/net/mace.h
@@ -164,7 +164,7 @@ struct mace {
/* Bits in UTR */
#define RTRE 0x80 /* reserved test register enable. DON'T SET. */
#define RTRD 0x40 /* reserved test register disable. Sticky */
-#define RPA 0x20 /* accept runt packets */
+#define RPAC 0x20 /* accept runt packets */
#define FCOLL 0x10 /* force collision */
#define RCVFCSE 0x08 /* receive FCS enable */
#define LOOP_NONE 0x00 /* no loopback */
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 87b808754..10cf51941 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -40,7 +40,6 @@ static const char *version =
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/system.h>
@@ -117,7 +116,7 @@ bad_clone_list[] __initdata = {
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned char pci_irq_line = 0;
+static unsigned int pci_irq_line = 0;
int ne_probe(struct device *dev);
static int ne_probe1(struct device *dev, int ioaddr);
@@ -182,7 +181,7 @@ __initfunc(int ne_probe(struct device *dev))
#ifdef CONFIG_PCI
/* Then look for any installed PCI clones */
- if (pcibios_present() && (ne_probe_pci(dev) == 0))
+ if (pci_present() && (ne_probe_pci(dev) == 0))
return 0;
#endif
@@ -207,27 +206,19 @@ __initfunc(static int ne_probe_pci(struct device *dev))
int i;
for (i = 0; pci_clone_list[i].vendor != 0; i++) {
- unsigned char pci_bus, pci_device_fn;
+ struct pci_dev *pdev = NULL;
unsigned int pci_ioaddr;
- int pci_index;
-
- for (pci_index = 0; pci_index < 8; pci_index++) {
- if (pcibios_find_device (pci_clone_list[i].vendor,
- pci_clone_list[i].dev_id, pci_index,
- &pci_bus, &pci_device_fn) != 0)
- break; /* No more of these type of cards */
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- /* Strip the I/O address out of the returned value */
- pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+
+ while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) {
+ pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
/* Avoid already found cards from previous calls */
if (check_region(pci_ioaddr, NE_IO_EXTENT))
continue;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- break; /* Beauty -- got a valid card. */
+ pci_irq_line = pdev->irq;
+ if (pci_irq_line) break; /* Found it */
}
- if (pci_irq_line == 0) continue; /* Try next PCI ID */
+ if (!pdev)
+ continue;
printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
pci_clone_list[i].name,
pci_ioaddr, pci_irq_line);
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 391714567..57d8cef9e 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -25,7 +25,6 @@ static const char *version = "pcnet32.c:v0.23 8.2.97 tsbogend@alpha.franken.de\n
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/init.h>
#include <asm/bitops.h>
#ifdef __mips__
@@ -83,7 +82,7 @@ static int pcnet32_debug = 1;
* in arch/i386/bios32.c
* v0.21: added endian conversion for ppc, from work by cort@cs.nmt.edu
* v0.22: added printing of status to ring dump
- * v0.23: changed enet_statistics to net_devive_stats
+ * v0.23: changed enet_statistics to net_device_stats
*/
@@ -177,7 +176,7 @@ static void pcnet32_set_multicast_list(struct device *dev);
__initfunc(int pcnet32_probe (struct device *dev))
{
unsigned int ioaddr = dev ? dev->base_addr: 0;
- unsigned char irq_line = dev ? dev->irq : 0;
+ unsigned int irq_line = dev ? dev->irq : 0;
int *port;
if (ioaddr > 0x1ff)
@@ -186,30 +185,20 @@ __initfunc(int pcnet32_probe (struct device *dev))
return ENXIO;
#if defined(CONFIG_PCI)
- if (pcibios_present()) {
- int pci_index;
+ if (pci_present()) {
+ struct pci_dev *pdev = NULL;
printk("pcnet32.c: PCI bios is present, checking for devices...\n");
- for (pci_index = 0; pci_index < 8; pci_index++) {
- unsigned char pci_bus, pci_device_fn;
+ while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) {
unsigned short pci_command;
- if (pcibios_find_device (PCI_VENDOR_ID_AMD,
- PCI_DEVICE_ID_AMD_LANCE, pci_index,
- &pci_bus, &pci_device_fn) != 0)
- break;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &irq_line);
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &ioaddr);
- /* Remove I/O space marker in bit 0. */
- ioaddr &= ~3;
+ irq_line = pdev->irq;
+ ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
/* PCI Spec 2.1 states that it is either the driver or PCI card's
* responsibility to set the PCI Master Enable Bit if needed.
* (From Mark Stockton <marks@schooner.sys.hou.compaq.com>)
*/
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
/* Avoid already found cards from previous pcnet32_probe() calls */
if (check_region(ioaddr, PCNET32_TOTAL_SIZE))
@@ -218,8 +207,7 @@ __initfunc(int pcnet32_probe (struct device *dev))
if ( ! (pci_command & PCI_COMMAND_MASTER)) {
printk("PCI Master Bit has not been set. Setting...\n");
pci_command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, pci_command);
+ pci_write_config_word(pdev, PCI_COMMAND, pci_command);
}
#ifdef __powerpc__
irq_line = 15;
diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c
index de70cd001..4db4094e2 100644
--- a/drivers/net/ppp.c
+++ b/drivers/net/ppp.c
@@ -8,7 +8,7 @@
* Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
* ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
*
- * ==FILEVERSION 980123==
+ * ==FILEVERSION 980319==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the number above to the
@@ -1326,6 +1326,10 @@ ppp_doframe (struct ppp *ppp)
(*ppp->sc_rcomp->incomp) (ppp->sc_rc_state,
data, count);
}
+ } else if (proto == PPP_COMP && (ppp->flags & SC_DEBUG)) {
+ printk(KERN_DEBUG "ppp: frame not decompressed: "
+ "flags=%x, count=%d, sc_rc_state=%p\n",
+ ppp->flags, count, ppp->sc_rc_state);
}
/*
* Process the uncompressed frame.
@@ -1659,6 +1663,9 @@ static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd)
}
break;
}
+ if (ppp->flags & SC_DEBUG)
+ printk(KERN_DEBUG "ppp_proto_ccp: %s code %d, flags=%x\n",
+ (rcvd? "rcvd": "sent"), CCP_CODE(dp), ppp->flags);
restore_flags(flags);
}
@@ -1977,16 +1984,15 @@ ppp_dev_xmit_frame (struct ppp *ppp, struct ppp_buffer *buf,
(control == PPP_UI) &&
(proto != PPP_LCP) &&
(proto != PPP_CCP)) {
- new_data = kmalloc (ppp->mtu, GFP_ATOMIC);
+ new_data = kmalloc (ppp->mtu + PPP_HDRLEN, GFP_ATOMIC);
if (new_data == NULL) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_dev_xmit_frame: no memory\n");
+ printk (KERN_ERR "ppp_dev_xmit_frame: no memory\n");
return 1;
}
new_count = (*ppp->sc_xcomp->compress)
- (ppp->sc_xc_state, data, new_data, count, ppp->mtu);
+ (ppp->sc_xc_state, data, new_data, count,
+ ppp->mtu + PPP_HDRLEN);
if (new_count > 0 && (ppp->flags & SC_CCP_UP)) {
ppp_dev_xmit_lower (ppp, buf, new_data, new_count, 0);
@@ -2153,7 +2159,7 @@ out:
}
/*
- * Process the BSD compression IOCTL event for the tty device.
+ * Process the set-compression ioctl.
*/
static int
@@ -2187,7 +2193,7 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp)
save_flags(flags);
cli();
- ppp->flags &= ~(SC_COMP_RUN | SC_DECOMP_RUN);
+ ppp->flags &= ~(data.transmit? SC_COMP_RUN: SC_DECOMP_RUN);
restore_flags(flags);
cp = find_compressor (ccp_option[0]);
@@ -2257,8 +2263,9 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
unsigned int param2, unsigned long param3)
{
struct ppp *ppp = tty2ppp (tty);
- register int temp_i = 0;
+ register int temp_i = 0, oldflags;
int error = 0;
+ unsigned long flags;
/*
* Verify the status of the PPP device.
*/
@@ -2308,16 +2315,18 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
if (error != 0)
break;
temp_i &= SC_MASK;
- temp_i |= (ppp->flags & ~SC_MASK);
- if ((ppp->flags & SC_CCP_OPEN) &&
- (temp_i & SC_CCP_OPEN) == 0)
- ppp_ccp_closed (ppp);
+ if ((ppp->flags & SC_CCP_OPEN) && (temp_i & SC_CCP_OPEN) == 0)
+ ppp_ccp_closed(ppp);
- if ((ppp->flags | temp_i) & SC_DEBUG)
+ save_flags(flags);
+ cli();
+ oldflags = ppp->flags;
+ ppp->flags = temp_i |= (ppp->flags & ~SC_MASK);
+ restore_flags(flags);
+ if ((oldflags | temp_i) & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: set flags to %x\n", temp_i);
- ppp->flags = temp_i;
break;
/*
* Set the compression mode
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
index edb3d10f7..4862b9398 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp_deflate.c
@@ -1,5 +1,5 @@
/*
- * ==FILEVERSION 971001==
+ * ==FILEVERSION 980319==
*
* ppp_deflate.c - interface the zlib procedures for Deflate compression
* and decompression (as used by gzip) to the PPP code.
@@ -188,20 +188,21 @@ z_comp_alloc(options, opt_len)
struct ppp_deflate_state *state;
int w_size;
- MOD_INC_USE_COUNT;
- if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+ if (opt_len != CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| options[3] != DEFLATE_CHK_SEQUENCE)
- goto out_fail;
+ return NULL;
w_size = DEFLATE_SIZE(options[2]);
if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
- goto out_fail;
+ return NULL;
state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
- goto out_fail;
+ return NULL;
+ MOD_INC_USE_COUNT;
memset (state, 0, sizeof (struct ppp_deflate_state));
state->strm.next_in = NULL;
state->strm.zalloc = zalloc_init;
@@ -217,7 +218,6 @@ z_comp_alloc(options, opt_len)
out_free:
z_comp_free(state);
-out_fail:
MOD_DEC_USE_COUNT;
return NULL;
}
@@ -230,7 +230,8 @@ z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
{
struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
- if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+ if (opt_len < CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| DEFLATE_SIZE(options[2]) != state->w_size
@@ -264,7 +265,7 @@ z_compress(arg, rptr, obuf, isize, osize)
int isize, osize;
{
struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
- int r, proto, off, olen;
+ int r, proto, off, olen, oavail;
unsigned char *wptr;
/*
@@ -291,9 +292,10 @@ z_compress(arg, rptr, obuf, isize, osize)
wptr += PPP_HDRLEN;
wptr[0] = state->seqno >> 8;
wptr[1] = state->seqno;
- wptr += 2;
+ wptr += DEFLATE_OVHD;
+ olen = PPP_HDRLEN + DEFLATE_OVHD;
state->strm.next_out = wptr;
- state->strm.avail_out = osize - (PPP_HDRLEN + 2);
+ state->strm.avail_out = oavail = osize - olen;
++state->seqno;
off = (proto > 0xff) ? 2 : 3; /* skip 1st proto byte if 0 */
@@ -301,25 +303,23 @@ z_compress(arg, rptr, obuf, isize, osize)
state->strm.next_in = rptr;
state->strm.avail_in = (isize - off);
- olen = 0;
for (;;) {
r = deflate(&state->strm, Z_PACKET_FLUSH);
if (r != Z_OK) {
if (state->debug)
- printk(KERN_DEBUG "z_compress: deflate returned %d (%s)\n",
- r, (state->strm.msg? state->strm.msg: ""));
+ printk(KERN_ERR
+ "z_compress: deflate returned %d\n", r);
break;
}
if (state->strm.avail_out == 0) {
- olen += osize;
+ olen += oavail;
state->strm.next_out = NULL;
- state->strm.avail_out = 1000000;
+ state->strm.avail_out = oavail = 1000000;
} else {
break; /* all done */
}
}
- if (olen < osize)
- olen += osize - state->strm.avail_out;
+ olen += oavail - state->strm.avail_out;
/*
* See if we managed to reduce the size of the packet.
@@ -372,19 +372,21 @@ z_decomp_alloc(options, opt_len)
struct ppp_deflate_state *state;
int w_size;
- MOD_INC_USE_COUNT;
- if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+ if (opt_len != CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| options[3] != DEFLATE_CHK_SEQUENCE)
- goto out_fail;
+ return NULL;
w_size = DEFLATE_SIZE(options[2]);
if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
- goto out_fail;
+ return NULL;
state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
- goto out_fail;
+ return NULL;
+
+ MOD_INC_USE_COUNT;
memset (state, 0, sizeof (struct ppp_deflate_state));
state->w_size = w_size;
state->strm.next_out = NULL;
@@ -398,7 +400,6 @@ z_decomp_alloc(options, opt_len)
out_free:
z_decomp_free(state);
-out_fail:
MOD_DEC_USE_COUNT;
return NULL;
}
@@ -411,7 +412,8 @@ z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
{
struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
- if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+ if (opt_len < CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| DEFLATE_SIZE(options[2]) != state->w_size
@@ -543,8 +545,12 @@ z_decompress(arg, ibuf, isize, obuf, osize)
}
}
- if (decode_proto)
+ if (decode_proto) {
+ if (state->debug)
+ printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",
+ state->unit);
return DECOMP_ERROR;
+ }
olen = osize + overflow - state->strm.avail_out;
state->stats.unc_bytes += olen;
@@ -634,6 +640,23 @@ struct compressor ppp_deflate = {
z_comp_stats, /* decomp_stat */
};
+struct compressor ppp_deflate_draft = {
+ CI_DEFLATE_DRAFT, /* compress_proto */
+ z_comp_alloc, /* comp_alloc */
+ z_comp_free, /* comp_free */
+ z_comp_init, /* comp_init */
+ z_comp_reset, /* comp_reset */
+ z_compress, /* compress */
+ z_comp_stats, /* comp_stat */
+ z_decomp_alloc, /* decomp_alloc */
+ z_decomp_free, /* decomp_free */
+ z_decomp_init, /* decomp_init */
+ z_decomp_reset, /* decomp_reset */
+ z_decompress, /* decompress */
+ z_incomp, /* incomp */
+ z_comp_stats, /* decomp_stat */
+};
+
#ifdef MODULE
/*************************************************************
* Module support routines
@@ -646,6 +669,7 @@ init_module(void)
if (answer == 0)
printk (KERN_INFO
"PPP Deflate Compression module registered\n");
+ ppp_register_compressor(&ppp_deflate_draft);
return answer;
}
@@ -655,7 +679,9 @@ cleanup_module(void)
if (MOD_IN_USE)
printk (KERN_INFO
"Deflate Compression module busy, remove delayed\n");
- else
+ else {
ppp_unregister_compressor (&ppp_deflate);
+ ppp_unregister_compressor (&ppp_deflate_draft);
+ }
}
#endif
diff --git a/drivers/net/sdla_fr.c b/drivers/net/sdla_fr.c
index 9c1c65af8..79bd5d4ca 100644
--- a/drivers/net/sdla_fr.c
+++ b/drivers/net/sdla_fr.c
@@ -83,7 +83,6 @@
* Jan 02, 1997 Gene Kozin Initial version.
*****************************************************************************/
-#include <linux/config.h> /* OS configuration options */
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/sdla_ppp.c b/drivers/net/sdla_ppp.c
index 32675d355..fa4f98d61 100644
--- a/drivers/net/sdla_ppp.c
+++ b/drivers/net/sdla_ppp.c
@@ -56,7 +56,6 @@
* Jan 06, 1997 Gene Kozin Initial version.
*****************************************************************************/
-#include <linux/config.h> /* OS configuration options */
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/sdla_x25.c b/drivers/net/sdla_x25.c
index 6a649a2d2..6a1759040 100644
--- a/drivers/net/sdla_x25.c
+++ b/drivers/net/sdla_x25.c
@@ -42,7 +42,6 @@
#error This code MUST be compiled as a kernel module!
#endif
-#include <linux/config.h> /* OS configuration options */
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 7a4ceca36..79d6d8076 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -306,9 +306,9 @@ static int ultramca_close_card(struct device *dev)
#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */
#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_ULTRA_CARDS] = { 0, };
+static char namelist[NAMELEN * MAX_ULTRAMCA_CARDS] = { 0, };
-static struct device dev_ultra[MAX_ULTRA_CARDS] =
+static struct device dev_ultra[MAX_ULTRAMCA_CARDS] =
{
{
NULL, /* assign a chunk of namelist[] below */
@@ -318,11 +318,11 @@ static struct device dev_ultra[MAX_ULTRA_CARDS] =
},
};
-static int io[MAX_ULTRA_CARDS] = { 0, };
-static int irq[MAX_ULTRA_CARDS] = { 0, };
+static int io[MAX_ULTRAMCA_CARDS] = { 0, };
+static int irq[MAX_ULTRAMCA_CARDS] = { 0, };
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
@@ -331,7 +331,7 @@ int init_module(void)
{
int this_dev, found = 0;
- for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++)
+ for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++)
{
struct device *dev = &dev_ultra[this_dev];
dev->name = namelist+(NAMELEN*this_dev);
@@ -360,7 +360,7 @@ void cleanup_module(void)
{
int this_dev;
- for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++)
+ for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++)
{
struct device *dev = &dev_ultra[this_dev];
if (dev->priv != NULL)
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index c4f6543a0..a3d3abebf 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -239,8 +239,9 @@ __initfunc(int ultra32_probe1(struct device *dev, int ioaddr))
static int ultra32_open(struct device *dev)
{
int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */
+ int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : SA_SHIRQ;
- if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev))
+ if (request_irq(dev->irq, ei_interrupt, irq_flags, ei_status.name, dev))
return -EAGAIN;
outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 9ff5a4f11..ebe502604 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -45,7 +45,6 @@ static char *version =
#ifdef CONFIG_PCI
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <asm/pbm.h>
#endif
@@ -55,7 +54,10 @@ static char *version =
static struct happy_meal *root_happy_dev = NULL;
#endif
-/* #define HMEDEBUG */
+#undef HMEDEBUG
+#undef SXDEBUG
+#undef RXDEBUG
+#undef TXDEBUG
#ifdef HMEDEBUG
#define HMD(x) printk x
@@ -1406,27 +1408,15 @@ static int happy_meal_is_not_so_happy(struct happy_meal *hp,
{
int reset = 0;
- printk("%s: Error interrupt for happy meal, status = %08lx\n",
- hp->dev->name, status);
-
- if(status &
- (GREG_STAT_RCNTEXP|GREG_STAT_ACNTEXP|GREG_STAT_CCNTEXP|GREG_STAT_LCNTEXP)) {
- /* Some stupid counter expired, we should be not
- * have interrupts for this enabled, but we check
- * for it anyways.
- */
-
- printk("%s: Happy Meal counters expired [ ", hp->dev->name);
- if(status & GREG_STAT_RCNTEXP)
- printk("ReceiveFrame ");
- if(status & GREG_STAT_ACNTEXP)
- printk("AlignError ");
- if(status & GREG_STAT_CCNTEXP)
- printk("CrcError ");
- if(status & GREG_STAT_LCNTEXP)
- printk("LengthError ");
- printk("]\n");
- }
+ /* Only print messages for non-counter related interrupts. */
+ if(status & (GREG_STAT_RFIFOVF | GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND |
+ GREG_STAT_MAXPKTERR | GREG_STAT_NORXD | GREG_STAT_RXERR |
+ GREG_STAT_RXPERR | GREG_STAT_RXTERR | GREG_STAT_EOPERR |
+ GREG_STAT_MIFIRQ | GREG_STAT_TXEACK | GREG_STAT_TXLERR |
+ GREG_STAT_TXPERR | GREG_STAT_TXTERR | GREG_STAT_SLVERR |
+ GREG_STAT_SLVPERR))
+ printk("%s: Error interrupt for happy meal, status = %08lx\n",
+ hp->dev->name, status);
if(status & GREG_STAT_RFIFOVF) {
/* The receive FIFO overflowwed, usually a DMA error. */
@@ -1434,11 +1424,6 @@ static int happy_meal_is_not_so_happy(struct happy_meal *hp,
reset = 1;
}
- if(status & GREG_STAT_CVCNTEXP) {
- /* See above about counter expiration... */
- printk("%s: Code Violation error counter expired.\n", hp->dev->name);
- }
-
if(status & GREG_STAT_STSTERR) {
/* BigMAC SQE link test failed. */
printk("%s: Happy Meal BigMAC SQE test failed.\n", hp->dev->name);
@@ -1460,32 +1445,6 @@ static int happy_meal_is_not_so_happy(struct happy_meal *hp,
reset = 1;
}
- if(status & (GREG_STAT_NCNTEXP|GREG_STAT_ECNTEXP|GREG_STAT_LCCNTEXP|
- GREG_STAT_FCNTEXP)) {
- /* More stupid error counters... */
- printk("%s: Happy Meal counters expired [ ", hp->dev->name);
- if(status & GREG_STAT_NCNTEXP)
- printk("NormalCollision ");
- if(status & GREG_STAT_ECNTEXP)
- printk("ExcessCollision ");
- if(status & GREG_STAT_LCCNTEXP)
- printk("LateCollision ");
- if(status & GREG_STAT_FCNTEXP)
- printk("FirstCollision ");
- printk("]\n");
- }
-
- if(status & GREG_STAT_DTIMEXP) {
- /* Defer-timer expired. Probably means the happy meal needed
- * to back off too much before it could transmit one frame.
- */
-#if 0 /* XXX This isn't worth reporting and is in fact a normal condition. */
- printk("%s: Transmit defer timer expired, subnet congested?\n",
- hp->dev->name);
- reset = 1;
-#endif
- }
-
if(status & GREG_STAT_NORXD) {
/* AIEEE, out of receive descriptors. Check out our drop
* processing in happy_meal_rx to see how we try very hard
@@ -1584,8 +1543,11 @@ static inline void happy_meal_mif_interrupt(struct happy_meal *hp,
happy_meal_poll_stop(hp, tregs);
}
-/* #define TXD(x) printk x */
+#ifdef TXDEBUG
+#define TXD(x) printk x
+#else
#define TXD(x)
+#endif
static inline void happy_meal_tx(struct happy_meal *hp)
{
@@ -1676,8 +1638,11 @@ static inline void sun4c_happy_meal_tx(struct happy_meal *hp)
TXD((">"));
}
-/* #define RXD(x) printk x */
+#ifdef RXDEBUG
+#define RXD(x) printk x
+#else
#define RXD(x)
+#endif
/* Originally I use to handle the allocation failure by just giving back just
* that one ring buffer to the happy meal. Problem is that usually when that
@@ -1705,7 +1670,7 @@ static inline void happy_meal_rx(struct happy_meal *hp, struct device *dev,
/* Check for errors. */
if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
- RXD(("ERR(%08lx)]", flags));
+ RXD(("ERR(%08x)]", flags));
hp->net_stats.rx_errors++;
if(len < ETH_ZLEN)
hp->net_stats.rx_length_errors++;
@@ -1724,11 +1689,8 @@ static inline void happy_meal_rx(struct happy_meal *hp, struct device *dev,
}
skb = hp->rx_skbs[elem];
#ifdef NEED_DMA_SYNCHRONIZATION
-#ifdef CONFIG_PCI
- if(!(hp->happy_flags & HFLAG_PCI))
-#endif
- mmu_sync_dma(kva_to_hva(hp, skb->data),
- skb->len, hp->happy_sbus_dev->my_bus);
+ mmu_sync_dma(kva_to_hva(hp, skb->data),
+ skb->len, hp->happy_sbus_dev->my_bus);
#endif
if(len > RX_COPY_THRESHOLD) {
struct sk_buff *new_skb;
@@ -1819,7 +1781,7 @@ static inline void pci_happy_meal_rx(struct happy_meal *hp, struct device *dev,
/* Check for errors. */
if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
- RXD(("ERR(%08lx)]", flags));
+ RXD(("ERR(%08x)]", flags));
hp->net_stats.rx_errors++;
if(len < ETH_ZLEN)
hp->net_stats.rx_length_errors++;
@@ -1926,7 +1888,7 @@ static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct device *dev
/* Check for errors. */
if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
- RXD(("ERR(%08lx)]", flags));
+ RXD(("ERR(%08x)]", flags));
hp->net_stats.rx_errors++;
if(len < ETH_ZLEN)
hp->net_stats.rx_length_errors++;
@@ -1975,7 +1937,7 @@ static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct hmeal_tcvregs *tregs = hp->tcvregs;
unsigned int happy_status = hme_read32(hp, &gregs->stat);
- HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+ HMD(("happy_meal_interrupt: status=%08x ", happy_status));
dev->interrupt = 1;
@@ -2020,7 +1982,7 @@ static void pci_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs
struct hmeal_tcvregs *tregs = hp->tcvregs;
unsigned int happy_status = readl((unsigned long)&gregs->stat);
- HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+ HMD(("happy_meal_interrupt: status=%08x ", happy_status));
dev->interrupt = 1;
@@ -2065,7 +2027,7 @@ static void sun4c_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *re
struct hmeal_tcvregs *tregs = hp->tcvregs;
unsigned int happy_status = hme_read32(hp, &gregs->stat);
- HMD(("happy_meal_interrupt: status=%08lx ", happy_status));
+ HMD(("happy_meal_interrupt: status=%08x ", happy_status));
dev->interrupt = 1;
@@ -2181,8 +2143,11 @@ static int happy_meal_close(struct device *dev)
return 0;
}
-/* #define SXD(x) printk x */
+#ifdef SXDEBUG
+#define SXD(x) printk x
+#else
#define SXD(x)
+#endif
static int happy_meal_start_xmit(struct sk_buff *skb, struct device *dev)
{
@@ -2700,19 +2665,20 @@ __initfunc(int happy_meal_probe(struct device *dev))
}
}
#ifdef CONFIG_PCI
- if(pcibios_present()) {
+ if(pci_present()) {
struct pci_dev *pdev;
- for(pdev = pci_devices; pdev; pdev = pdev->next) {
+ pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+ PCI_DEVICE_ID_SUN_HAPPYMEAL, 0);
+ while (pdev) {
if(cards)
dev = NULL;
- if((pdev->vendor == PCI_VENDOR_ID_SUN) &&
- (pdev->device == PCI_DEVICE_ID_SUN_HAPPYMEAL)) {
- cards++;
- if((v = happy_meal_pci_init(dev, pdev)))
- return v;
- }
-
+ cards++;
+ if((v = happy_meal_pci_init(dev, pdev)))
+ return v;
+ pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+ PCI_DEVICE_ID_SUN_HAPPYMEAL,
+ pdev);
}
}
#endif
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 093f7a181..4edbeba69 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.69 1998/01/09 16:42:52 jj Exp $
+/* $Id: sunlance.c,v 1.74 1998/02/12 07:37:25 davem Exp $
* lance.c: Linux/Sparc/Lance driver
*
* Written 1995, 1996 by Miguel de Icaza
@@ -66,6 +66,7 @@ static char *version =
static char *lancestr = "LANCE";
static char *lancedma = "LANCE DMA";
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -103,6 +104,9 @@ static char *lancedma = "LANCE DMA";
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+
/* Define: 2^4 Tx buffers and 2^4 Rx buffers */
#ifndef LANCE_LOG_TX_BUFFERS
#define LANCE_LOG_TX_BUFFERS 4
@@ -1037,7 +1041,7 @@ sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
"busmaster-regval",
(LE_C3_BSWP | LE_C3_ACON |
LE_C3_BCON));
-
+
lp->ll = ll;
lp->name = lancestr;
lp->ledma = ledma;
@@ -1119,8 +1123,9 @@ no_link_test:
dev->hard_start_xmit = &lance_start_xmit;
dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &lance_set_multicast;
-
+
dev->irq = (unsigned char) sdev->irqs [0].pri;
+
dev->dma = 0;
ether_setup (dev);
@@ -1144,6 +1149,31 @@ find_ledma (struct linux_sbus_device *dev)
return 0;
}
+#ifdef CONFIG_SUN4
+
+#include <asm/sun4paddr.h>
+
+/* Find all the lance cards on the system and initialize them */
+__initfunc(int sparc_lance_probe (struct device *dev))
+{
+ static struct linux_sbus_device sdev;
+ static int called = 0;
+
+ if(called)
+ return ENODEV;
+ called++;
+
+ if (idprom->id_machtype == (SM_SUN4|SM_4_330)) {
+ memset (&sdev, 0, sizeof(sdev));
+ sdev.reg_addrs[0].phys_addr = SUN4_300_ETH_PHYSADDR;
+ sdev.irqs[0].pri = 6;
+ return sparc_lance_init(dev, &sdev, 0, 0);
+ }
+ return ENODEV;
+}
+
+#else /* !CONFIG_SUN4 */
+
/* Find all the lance cards on the system and initialize them */
__initfunc(int sparc_lance_probe (struct device *dev))
{
@@ -1152,10 +1182,11 @@ __initfunc(int sparc_lance_probe (struct device *dev))
struct Linux_SBus_DMA *ledma = 0;
static int called = 0;
int cards = 0, v;
-
+
if(called)
return ENODEV;
called++;
+
for_each_sbus (bus) {
for_each_sbusdev (sdev, bus) {
if (cards) dev = NULL;
@@ -1186,6 +1217,7 @@ __initfunc(int sparc_lance_probe (struct device *dev))
return ENODEV;
return 0;
}
+#endif /* !CONFIG_SUN4 */
#ifdef MODULE
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index cef3f54a4..92d4b9e69 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -29,7 +29,6 @@
#include "tlan.h"
-#include <linux/bios32.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/etherdevice.h>
@@ -96,7 +95,7 @@ static TLanPciId TLanDeviceList[] = {
};
-static int TLan_PciProbe( u8 *, u8 *, u8 *, u8 *, u32 *, u32 * );
+static int TLan_PciProbe( u8 *, u8 *, int *, u8 *, u32 *, u32 * );
static int TLan_Init( struct device * );
static int TLan_Open(struct device *dev);
static int TLan_StartTx(struct sk_buff *, struct device *);
@@ -193,7 +192,7 @@ extern int init_module(void)
int failed;
int found;
u32 io_base;
- u8 irq;
+ int irq;
u8 rev;
printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n",
@@ -319,7 +318,8 @@ extern int tlan_probe( struct device *dev )
static int pad_allocated = 0;
int found;
TLanPrivateInfo *priv;
- u8 bus, dfn, irq, rev;
+ u8 bus, dfn, rev;
+ int irq;
u32 io_base, dl_ix;
found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix );
@@ -398,7 +398,7 @@ extern int tlan_probe( struct device *dev )
*
**************************************************************/
-int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
+int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
{
static int dl_index = 0;
static int pci_index = 0;
@@ -409,7 +409,7 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
int reg;
- if ( ! pcibios_present() ) {
+ if ( ! pci_present() ) {
printk( "TLAN: PCI Bios not present.\n" );
return 0;
}
@@ -425,6 +425,7 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
);
if ( ! not_found ) {
+ struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn);
TLAN_DBG(
TLAN_DEBUG_GNRL,
@@ -433,19 +434,18 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_
TLanDeviceList[dl_index].deviceId
);
- pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_REVISION_ID, pci_rev);
- pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_INTERRUPT_LINE, pci_irq);
- pcibios_read_config_word ( *pci_bus, *pci_dfn, PCI_COMMAND, &pci_command);
- pcibios_read_config_dword( *pci_bus, *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_base);
- pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev);
+ *pci_irq = pdev->irq;
+ pci_read_config_word ( pdev, PCI_COMMAND, &pci_command);
+ pci_read_config_byte ( pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 0x10) {
- pcibios_write_config_byte( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, 0xff);
+ pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 0xff);
TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Setting latency timer to max.\n");
}
- for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg +=4 ) {
- pcibios_read_config_dword( *pci_bus, *pci_dfn, reg, pci_io_base);
+ for ( reg = 0; reg <= 5; reg ++ ) {
+ *pci_io_base = pdev->base_address[reg];
if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {
*pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;
TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: IO mapping is available at %x.\n", *pci_io_base);
diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c
index 035c47a5c..0abf814e5 100644
--- a/drivers/net/tulip.c
+++ b/drivers/net/tulip.c
@@ -82,7 +82,6 @@ static const rx_copybreak = 100;
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
@@ -125,8 +124,10 @@ char kernel_version[] = UTS_RELEASE;
#include <linux/delay.h>
#endif
#if (LINUX_VERSION_CODE >= 0x20100)
+#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
#endif
+#endif
#ifdef SA_SHIRQ
#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
#else
@@ -135,6 +136,7 @@ char kernel_version[] = UTS_RELEASE;
#if (LINUX_VERSION_CODE < 0x20123)
#define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
#endif
/* This my implementation of shared IRQs, now only used for 1.2.13. */
@@ -453,11 +455,17 @@ int tulip_probe(struct device *dev)
well with the current structure. So instead we detect just the
Tulip cards in slot order. */
- if (pcibios_present()) {
+ if (pci_present()) {
unsigned char pci_bus, pci_device_fn;
for (;pci_index < 0xff; pci_index++) {
- unsigned char pci_irq_line, pci_latency;
+ unsigned char pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+ unsigned int pci_irq_line;
+ struct pci_dev *pdev;
+#else
+ unsigned char pci_irq_line;
+#endif
unsigned short pci_command, vendor, device;
unsigned int pci_ioaddr, chip_idx = 0;
@@ -473,10 +481,16 @@ int tulip_probe(struct device *dev)
PCI_VENDOR_ID, &vendor);
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+ pdev = pci_find_slot(pci_bus, pci_device_fn);
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pdev->base_address[0];
+#else
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_INTERRUPT_LINE, &pci_irq_line);
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
/* Remove I/O space marker in bit 0. */
pci_ioaddr &= ~3;