@@ -129,6+129,15 @@ N: Ross Biro E: bir7@leland.Stanford.Edu
D: Original author of the Linux networking code
+N: Philip Blundell
+E: pjb27@cam.ac.uk
+E: pb@nexus.co.uk
+E: phil@tazenda.demon.co.uk
+D: Device driver hacking (especially EtherExpress16/3C505 net cards)
+D: Some Linux/ARM stuff
+S: Trinity College
+S: Cambridge, UK. CB2 1TQ
+
N: Thomas Bogendoerfer
E: tsbogend@bigbug.franken.de
D: Lance32 driver
@@ -545,6+554,13 @@ S: Muehlenweg 19 S: 34266 Niestetal
S: Germany
+N: Richard Henderson
+E: rth@tamu.edu
+D: Alpha/ELF, gcc, binutils, and glibc
+S: 304 E. North Ave.
+S: Bryan, TX 77801-3431
+S: USA
+
N: Sebastian Hetze
E: she@lunetix.de
D: German Linux Documentation,
@@ -568,6+584,14 @@ S: 46030 Manekin Plaza, Suite 160 S: Dulles, Virginia 20166
S: USA
+N: Kenji Tsutomu Hollis
+E: khollis@bitgate.com
+W: http://www.nurk.org/
+D: Berkshire PC Watchdog Driver
+S: PO Box 15
+S: Grants Pass, OR 97526
+S: USA
+
N: Nick Holloway
E: Nick.Holloway@alfie.demon.co.uk
E: Nick.Holloway@parallax.co.uk
@@ -26,11+26,11 @@ http://slug.ctv.es/~alfredo/Cambios.html. valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
http://www.datanet.hu/generations/linux/newkernel.html.
- For people who prefer Japanse (thanks to Mitsuhiro Kojima): Kono
-bunshou no nihongo ban ha
+ For people who prefer Japanese (thanks to Mitsuhiro Kojima): Kono
+bunshou no nihongo ban wa
http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
-Last updated: July 29, 1996.
+Last updated: August 6, 1996.
Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Releases
@@ -135,6+135,18 @@ there's an unofficial libc-4.7.6 release out to which you can upgrade to fix this problem. Libc is available from
ftp://sunsite.unc.edu/pub/Linux/GCC/.
+GCC Signal 11 error
+===================
+
+ Many people have been reporting messages like the following,
+especially when compiling a new kernel:
+
+ `gcc: Internal compiler error: program cc1 got fatal signal 11'.
+
+ This is NOT a kernel bug. Rather, these messages are generally
+caused by hardware problems. See http://www.bitwizard.nl/sig11/ for
+the sig11 FAQ.
+
Procps utilities
================
@@ -259,7+271,11 @@ the following as root: ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz. If you
upgrade to this release read the `README' file contained into the
package to get some important information about the `tgetent' function
-changes!
+changes! Note that there is now a fixed version at
+ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.fix. If some of your
+apps complain that termcap entries are too long and you don't need some
+of the more esoteric terms in the standard 2.0.8 termcap, just download
+termcap-2.0.8.fix and move it to /etc/termcap.
Also, the console driver is now responsible for keeping track of
correspondence between character codes and glyph bitmaps. If you
@@ -271,7+287,7 @@ Hdparm
Hdparm has been upgraded to take advantage of the latest features of
the kernel drivers. The latest non-beta version can be found at
-ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.0.tar.gz.
+ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.1.tar.gz.
IP Accounting
=============
@@ -285,7+301,7 @@ direction (either incoming or outgoing). There also exists a possibility to match on device names and/or
device addresses, so that only packets coming in/going out via that
device (network interface) match with a rule. You'll need to get
-ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to
+ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to
use this.
IP Firewalls
@@ -298,7+314,7 @@ exists a possibility to match on device names and/or device addresses, so that only packets coming in/going out via that device (network
interface) match with a rule. This is especially useful to prevent
spoofing. You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to use this.
+ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
IP Masquerading
===============
@@ -307,7+323,7 @@ IP Masquerading always need to load separate modules (ip_masq_ftp.o and/or
ip_masq_irc.o) if you are going to use FTP or IRC in combination with
masquerading. You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to use this.
+ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
ISDN support
============
@@ -473,9+489,9 @@ Cyclades Serial Driver ======================
The Cyclades driver has been changed so that the minor numbers start
-at 0 instead of 32 (ie: ttyC0 should be major 19, minor 0 in the 2.0.x
-kernels while it used to be major 19, minor 32 in the older kernels).
-You can use mknod to manually fix this or use a newer version of MAKEDEV.
+at 0 instead of 32 (for example, ttyC0 should be major 19, minor 0 for
+2.0.x kernels; in older kernels, it would have been major 19, minor
+32). Use mknod or a sufficiently new version of MAKEDEV to fix this.
NCR 53c810 SCSI Driver
======================
While we're on the subject, changes made for the 2.0.x series cause
the connect() Perl (both 4 and 5) call to time out while connecting to
-remote systems. If you need the connect call for your program, use C
-instead of Perl.
+remote systems. The problem is not actually in the connect() call;
+rather, the optional bind() call usually used with connect() causes the
+problem. Remove the bind() call and your Perl scripts should connect.
Also, Perl scripts using the readdir call now misbehave if you're
using an old version of Perl, due to changes in libc. Upgrade to a
@@ -508,7+525,10 @@ when present at the end of a line, try setting an appropriate value (many have reported success with "latin1", for example) for the
environmental variable LESSCHARSET. Another, and probably better,
solution is to edit the file /usr/lib/man.config and change all
-`-Tlatin1' options to `-Tascii'.
+`-Tlatin1' options to `-Tascii'. An alternate solution, for those of
+you who can't reformat your man files in .../cat* directories is to
+edit /usr/lib/man.config, setting the PAGER to `PAGER
+(LESSCHARSET=latin1;export LESSCHARSET;/usr/bin/less -is'.
E2fsprogs
=========
@@ -3483,7+3483,7 @@ CONFIG_PCWATCHDOG it resets your computer after a certain amount of time. This driver is
like the WDT501 driver but for different hardware. The PC watchdog cards
can be ordered from http://www.berkprod.com. Some example rc.local files
- are available from ftp.bitgame.com.
+ are available from ftp.bitgate.com.
Enhanced Real Time Clock Support
CONFIG_RTC
@@ -257,7+257,7 @@ Summary of ide driver parameters for kernel "command line": older/odd IDE drives.
"idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz,
- where "xx" is between 25 and 66 inclusive,
+ where "xx" is between 20 and 66 inclusive,
used when tuning chipset PIO modes.
For PCI bus, 25 is correct for a P75 system,
30 is correct for P90,P120,P180 systems,
Ioctl Numbers
-12 Jun 1996
+6 Aug 1996
Michael Chastain
<mec@duracef.shout.net>
@@ -50,7+50,8 @@ Following the convention is good because: (5) When following the convention, the driver code can use generic
code to call verify_area to validate parameters.
-This table is current to Linux pre2.0.9.
+This table lists ioctls visible from user land for Linux/i386. It is
+current to Linux 2.0.11.
Code Seq# Include File Comments
========================================================
@@ -83,6+84,7 @@ Code Seq# Include File Comments 'T' all linux/soundcard.h conflict!
'T' all asm-i386/ioctls.h conflict!
'V' all linux/vt.h
+'W' 00-1F linux/pcwd.h
'Y' all linux/cyclades.h
'Z' all linux/scc.h version 2.2 of z8530drv
'a' all various, see http://lrcwww.epfl.ch/linux-atm/magic.html
@@ -86,7+86,7 @@ M gpg109@rsphy1.anu.edu.au L: linux-net@vger.rutgers.edu
S: Maintained
-ETHEREXPRESS NETWORK DRIVER
+ETHEREXPRESS-16 NETWORK DRIVER
P: Philip Blundell
M: pjb27@cam.ac.uk
L: linux-net@vger.rutgers.edu
VERSION = 2
PATCHLEVEL = 0
-SUBLEVEL = 11
+SUBLEVEL = 12
ARCH = i386
@@ -993,6+993,7 @@ static inline void sio_fixup(void) { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
{ 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
{ 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
+ { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
#endif
};
/*
@@ -1005,7+1006,21 @@ static inline void sio_fixup(void) * This probably ought to be configurable via MILO. For
* example, sound boards seem to like using IRQ 9.
*/
+#ifdef CONFIG_ALPHA_NONAME
+ /*
+ * For UDB, the only available PCI slot must not map to IRQ 9,
+ * since that's the builtin MSS sound chip. That PCI slot
+ * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+ * instead.
+ *
+ * Unfortunately we have to do this for NONAME as well, since
+ * they are co-indicated when the platform type "Noname" is
+ * selected... :-(
+ */
+ const unsigned int route_tab = 0x0b0a0f09;
+#else /* CONFIG_ALPHA_NONAME */
const unsigned int route_tab = 0x0b0a090f;
+#endif /* CONFIG_ALPHA_NONAME */
unsigned int level_bits;
unsigned char pin, slot;
int pirq;
@@ -1093,8+1108,13 @@ static inline void sio_fixup(void) * Now, make all PCI interrupts level sensitive. Notice:
* these registers must be accessed byte-wise. inw()/outw()
* don't work.
+ *
+ * Make sure to turn off any level bits set for IRQs 9,10,11,15,
+ * so that the only bits getting set are for devices actually found.
+ * Note that we do preserve the remainder of the bits, which we hope
+ * will be set correctly by ARC/SRM.
*/
- level_bits |= (inb(0x4d0) | (inb(0x4d1) << 8));
+ level_bits |= ((inb(0x4d0) | (inb(0x4d1) << 8)) & 0x71ff);
outb((level_bits >> 0) & 0xff, 0x4d0);
outb((level_bits >> 8) & 0xff, 0x4d1);
enable_ide(0x26e);
@@ -32,6+32,10 @@ extern void timer_interrupt(struct pt_regs * regs); # error Unable to handle more than 64 irq levels.
#endif
+/* Reserved interrupts. These must NEVER be requested by any driver!
+ */
+#define IS_RESERVED_IRQ(irq) ((irq)==2) /* IRQ 2 used by hw cascade */
+
/*
* Shadow-copy of masked interrupts.
* The bits are used as follows:
@@ -185,6+189,8 @@ int request_irq(unsigned int irq,
if (irq >= NR_IRQS)
return -EINVAL;
+ if (IS_RESERVED_IRQ(irq))
+ return -EINVAL;
if (!handler)
return -EINVAL;
p = irq_action + irq;
@@ -241,6+247,10 @@ void free_irq(unsigned int irq, void *dev_id) printk("Trying to free IRQ%d\n",irq);
return;
}
+ if (IS_RESERVED_IRQ(irq)) {
+ printk("Trying to free reserved IRQ %d\n", irq);
+ return;
+ }
for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
if (action->dev_id != dev_id)
continue;
#
#
-# Note : at this point, these files are compiled on all systems.
+# Note : at this point, these files are compiled on all systems.
# In the future, some of these should be built conditionally.
#
L_TARGET := block.a
-L_OBJS := ll_rw_blk.o genhd.o
+L_OBJS := ll_rw_blk.o genhd.o
M_OBJS :=
MOD_LIST_NAME := BLOCK_MODULES
LX_OBJS :=
/*
- * linux/drivers/block/cmd640.c Version 0.97 Aug 4, 1996
+ * linux/drivers/block/cmd640.c Version 0.99 Aug 6, 1996
*
* Copyright (C) 1995-1996 Linus Torvalds & authors (see below)
*/
* Version 0.96 prevent use of io_32bit when prefetch is off
* Version 0.97 fix VLB secondary interface for sjd@slip.net
* other minor tune-ups: 0.96 was very good.
+ * Version 0.98 ignore PCI version when disabled by BIOS
+ * Version 0.99 display setup/active/recovery clocks with PIO mode
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -119,6+121,7 @@ int cmd640_vlb = 0; #define VID 0x00
#define DID 0x02
#define PCMD 0x04
+#define PCMD_ENA 0x01
#define PSTTS 0x06
#define REVID 0x08
#define PROGIF 0x09
@@ -288,6+291,10 @@ static int match_pci_cmd640_device (void) if (get_cmd640_reg(i) != ven_dev[i])
return 0;
}
+ if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
+ printk("ide: cmd640 on PCI disabled by BIOS\n");
+ return 0;
+ }
return 1; /* success */
}
@@ -458,6+465,24 @@ static void set_prefetch_mode (unsigned int index, int mode) }
/*
+ * Dump out current drive clocks settings
+ */
+static void display_clocks (unsigned int index)
+{
+ byte active_count, recovery_count;
+
+ active_count = active_counts[index];
+ if (active_count == 1)
+ ++active_count;
+ recovery_count = recovery_counts[index];
+ if (active_count > 3 && recovery_count == 1)
+ ++recovery_count;
+ if (cmd640_chip_version > 1)
+ recovery_count += 1; /* cmd640b uses (count + 1)*/
+ printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count);
+}
+
+/*
* Pack active and recovery counts into single byte representation
* used by controller
*/
@@ -564,7+589,7 @@ static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cyc active_time = ide_pio_timings[pio_mode].active_time;
recovery_time = cycle_time - (setup_time + active_time);
clock_time = 1000 / bus_speed;
- cycle_count = (cycle_time + clock_time - 1) / clock_time;
+ cycle_count = (cycle_time + clock_time - 1) / clock_time;
setup_count = (setup_time + clock_time - 1) / clock_time;
@@ -635,12+660,13 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted) (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
cmd640_set_mode (index, d.pio_mode, d.cycle_time);
- printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s\n",
+ printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s",
drive->name,
d.pio_mode,
d.cycle_time,
d.use_iordy ? "w" : "wo",
d.overridden ? " (overriding vendor mode)" : "");
+ display_clocks(index);
}
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
@@ -784,8+810,9 @@ int ide_probe_for_cmd640x (void) */
retrieve_drive_counts (index);
check_prefetch (index);
- printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
+ printk("cmd640: drive%d timings/prefetch(%s) preserved",
index, drive->no_io_32bit ? "off" : "on");
+ display_clocks(index);
}
#else
/*
@@ -1685,15+1685,9 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
}
if (handler) {
- if(intr_count >= 2)
- {
- /* expected interrupt */
- floppy_tq.routine = (void *)(void *) handler;
- queue_task_irq(&floppy_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- }
- else
- handler();
+ /* expected interrupt */
+ floppy_tq.routine = (void *)(void *) handler;
+ queue_task_irq(&floppy_tq, &tq_timer);
} else
FDCS->reset = 1;
is_alive("normal interrupt end");
@@ -1931,8+1925,7 @@ static int wait_til_done(void (*handler)(void), int interruptible) unsigned long flags;
floppy_tq.routine = (void *)(void *) handler;
- queue_task(&floppy_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ queue_task(&floppy_tq, &tq_timer);
INT_OFF;
while(command_status < 2 && NO_SIGNAL){
is_alive("wait_til_done");
@@ -2740,8+2733,7 @@ static void redo_fd_request(void) if (TESTF(FD_NEED_TWADDLE))
twaddle();
floppy_tq.routine = (void *)(void *) floppy_start;
- queue_task(&floppy_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ queue_task(&floppy_tq, &tq_timer);
#ifdef DEBUGT
debugt("queue fd request");
#endif
@@ -2762,8+2754,7 @@ static struct tq_struct request_tq = static void process_fd_request(void)
{
cont = &rw_cont;
- queue_task(&request_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ queue_task(&request_tq, &tq_timer);
}
static void do_fd_request(void)
* fix missing restore_flags() in ide_ioctl
* prevent use of io_32bit on cmd640 with no prefetch
* Version 5.49 fix minor quirks in probing routines
+ * Version 5.50 allow values as small as 20 for idebus=
*
* Some additional driver compile-time options are in ide.h
*
@@ -2807,7+2808,7 @@ static int match_parm (char *s, const char *keywords[], int vals[], int max_vals * older/odd IDE drives.
*
* "idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz,
- * where "xx" is between 25 and 66 inclusive,
+ * where "xx" is between 20 and 66 inclusive,
* used when tuning chipset PIO modes.
* For PCI bus, 25 is correct for a P75 system,
* 30 is correct for P90,P120,P180 systems,
@@ -2912,10+2913,10 @@ void ide_setup (char *s) if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
if (match_parm(&s[6], NULL, vals, 1) != 1)
goto bad_option;
- if (vals[0] >= 25 && vals[0] <= 66)
+ if (vals[0] >= 20 && vals[0] <= 66)
idebus_parameter = vals[0];
else
- printk(" -- BAD BUS SPEED! Expected value from 25 to 66");
+ printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
goto done;
}
/*
#endif
#ifdef CONFIG_BLK_DEV_CMD640
-#if 1
+#if 0 /* change to 1 when debugging cmd640 problems */
void cmd640_dump_regs (void);
#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
#endif
**********************
+ v2.55 (96/08/05)
+ - A couple more messages moved to D_EXTRA.
+ - SLOW_XMIT_COPY off by default.
+ - Some tiny changes.
+
v2.54 (96/07/05)
- Under some situations, Stage 5 autoprobe was a little bit too
picky about the TXACK flag.
TO DO: (semi-prioritized)
- - Smarter recovery from RECON-during-transmit conditions.
+ - Support "arpless" mode like NetBSD does, and as recommended
+ by the (obsoleted) RFC1051.
+ - Smarter recovery from RECON-during-transmit conditions. (ie.
+ retransmit immediately)
- Make arcnetE_send_packet use arcnet_prepare_tx for loading the
packet into ARCnet memory.
- - Probe for multiple devices in one shot (trying to decide whether
- to do it the "ugly" way or not).
- - Add support for the new 1.3.x IP header cache features.
- - Debug level should be changed with a system call, not a hack to
- the "metric" flag.
+ - Some cards have shared memory with 4k mirrors instead of just 2k,
+ so we (uneventfully) find the "wrong" shmem when probing.
+ - Probe for multiple devices in one shot (trying to decide whether
+ to do it the "ugly" way or not).
+ - Add support for the new 1.3.x IP header cache, and other features.
+ - Debug level should be changed with a system call, not a hack to
+ the "metric" flag.
- What about cards with shared memory that can be "turned off?"
(or that have none at all, like the SMC PC500longboard)
- Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
*/
static const char *version =
- "arcnet.c: v2.54 96/07/05 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.55 96/08/05 Avery Pennarun <apenwarr@foxnet.net>\n";
@@ -244,11+254,11 @@ static const char *version = * defines; ARCnet probably is not the only driver that can screw up an
* ftape DMA transfer.
*
- * Turn this off if you don't have timing-sensitive DMA (ie. a tape drive)
- * and would like the little bit of speed back. It's on by default because
- * - trust me - it's very difficult to figure out that you need it!
+ * Turn this on if you have timing-sensitive DMA (ie. a tape drive) and
+ * would like to sacrifice a little bit of network speed to reduce tape
+ * write retries or some related problem.
*/
-#define SLOW_XMIT_COPY
+#undef SLOW_XMIT_COPY
/* The card sends the reconfiguration signal when it loses the connection to
* the rest of its network. It is a 'Hello, is anybody there?' cry. This
@@ -2310,7+2320,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
if (in->skb) /* already assembling one! */
{
- BUGMSG(D_NORMAL,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
kfree_skb(in->skb,FREE_WRITE);
@@ -2407,7+2417,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
if (in->skb && in->sequence!=arcsoft->sequence)
{
- BUGMSG(D_NORMAL,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+ BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
saddr,in->sequence,arcsoft->sequence,
arcsoft->split_flag);
kfree_skb(in->skb,FREE_WRITE);
@@ -2423,7+2433,7 @@ arcnetA_rx(struct device *dev,u_char *buf, arcsoft->split_flag);
if (in->skb) /* already assembling one! */
{
- BUGMSG(D_NORMAL,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
lp->stats.rx_errors++;
@@ -2437,7+2447,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
if (in->numpackets>16)
{
- BUGMSG(D_NORMAL,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+ BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
arcsoft->split_flag);
lp->stats.rx_errors++;
lp->stats.rx_length_errors++;
@@ -2477,7+2487,7 @@ arcnetA_rx(struct device *dev,u_char *buf, */
if (!in->skb)
{
- BUGMSG(D_NORMAL,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
arcsoft->split_flag,arcsoft->sequence);
lp->stats.rx_errors++;
lp->stats.rx_missed_errors++;
@@ -2490,7+2500,7 @@ arcnetA_rx(struct device *dev,u_char *buf, /* harmless duplicate? ignore. */
if (packetnum<=in->lastpacket-1)
{
- BUGMSG(D_NORMAL,"duplicate splitpacket ignored! (splitflag=%d)\n",
+ BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
arcsoft->split_flag);
lp->stats.rx_errors++;
lp->stats.rx_frame_errors++;
@@ -2498,7+2508,7 @@ arcnetA_rx(struct device *dev,u_char *buf, }
/* "bad" duplicate, kill reassembly */
- BUGMSG(D_NORMAL,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
+ BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
kfree_skb(in->skb,FREE_WRITE);
according to the terms of the GNU Public License,
incorporated herein by reference.
- The author may be reached at bao@saigon.async.com
+ The author may be reached at bao.ha@srs.gov
or 418 Hastings Place, Martinez, GA 30907.
Things remaining to do:
Better record keeping of errors.
Eliminate transmit interrupt to reduce overhead.
Implement "concurrent processing". I won't be doing it!
- Allow changes to the partition of the transmit and receive
- buffers, currently the ratio is 3:1 of receive to transmit
- buffer ratio.
Bugs:
Versions:
+ 0.09 Fixed a race condition in the transmit algorithm,
+ which causes crashes under heavy load with fast
+ pentium computers. The performance should also
+ improve a bit. The size of RX buffer, and hence
+ TX buffer, can also be changed via lilo or insmod.
+ (BCH, 7/31/96)
+
0.08 Implement 32-bit I/O for the 82595TX and 82595FX
based lan cards. Disable full-duplex mode if TPE
is not used. (BCH, 4/8/96)
*/
static const char *version =
- "eepro.c: v0.08 4/8/96 Bao C. Ha (bao.ha@srs.gov)\n";
+ "eepro.c: v0.09 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n";
#include <linux/module.h>
@@ -110,7+114,7 @@ static unsigned int eepro_portlist[] =
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
-#define NET_DEBUG 2
+#define NET_DEBUG 3
#endif
static unsigned int net_debug = NET_DEBUG;
@@ -180,15+184,26 @@ single packet. In other systems with faster computers and more congested network traffics, the ring linked list should improve performance by
allowing up to 8K worth of packets to be queued.
+The sizes of the receive and transmit buffers can now be changed via lilo
+or insmod. Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
+where rx-buffer is in KB unit. Modules uses the parameter mem which is
+also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
+The receive buffer has to be more than 3K or less than 29K. Otherwise,
+it is reset to the default of 24K, and, hence, 8K for the trasnmit
+buffer (transmit-buffer = 32K - receive-buffer).
+
*/
#define RAM_SIZE 0x8000
#define RCV_HEADER 8
-#define RCV_RAM 0x6000 /* 24KB for RCV buffer */
-#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */
-#define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) /* 0x5ffe */
-#define XMT_RAM (RAM_SIZE - RCV_RAM) /* 8KB for XMT buffer */
-#define XMT_LOWER_LIMIT (RCV_RAM >> 8) /* 0x6000 */
-#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */
+#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */
+#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */
+/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */ /* 0x5ffe */
+#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)
+/* #define XMT_RAM (RAM_SIZE - RCV_RAM) */ /* 8KB for XMT buffer */
+#define XMT_RAM (RAM_SIZE - (rcv_ram)) /* 8KB for XMT buffer */
+/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */ /* 0x6000 */
+#define XMT_LOWER_LIMIT ((rcv_ram) >> 8)
+#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */
#define XMT_HEADER 8
#define RCV_DONE 0x0008
@@ -368,6+383,16 @@ int eepro_probe1(struct device *dev, short ioaddr) dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
}
+
+ if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */
+ (dev->mem_end & 0x3f) > 29) /* and less than 29K */
+ dev->mem_end = RCV_RAM; /* or it will be set to 24K */
+ else dev->mem_end = 1024*dev->mem_end; /* Maybe I should shift << 10 */
+
+ /* From now on, dev->mem_end contains the actual size of rx buffer */
+
+ if (net_debug > 3)
+ printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
id = inb(ioaddr + REG3);
@@ -401,8+426,8 @@ int eepro_probe1(struct device *dev, short ioaddr) }
else printk(", %s.\n", ifmap[dev->if_port]);
- if ((dev->mem_start & 0xf) > 0)
- net_debug = dev->mem_start & 7;
+ if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */
+ net_debug = dev->mem_start & 7; /* still useful or not */
if (net_debug > 3) {
i = read_eeprom(ioaddr, 5);
@@ -516,7+541,7 @@ static int eepro_open(struct device *dev)
{
unsigned short temp_reg, old8, old9;
- int i, ioaddr = dev->base_addr;
+ int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
struct eepro_local *lp = (struct eepro_local *)dev->priv;
if (net_debug > 3)
@@ -654,6+679,7 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev) {
struct eepro_local *lp = (struct eepro_local *)dev->priv;
int ioaddr = dev->base_addr;
+ int rcv_ram = dev->mem_end;
if (net_debug > 5)
printk("eepro: entering eepro_send_packet routine.\n");
@@ -662,12+688,13 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev) /* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
+ if (tickssofar < 40)
return 1;
if (net_debug > 1)
printk("%s: transmit timed out, %s?\n", dev->name,
"network cable problem");
lp->stats.tx_errors++;
+
/* Try to restart the adaptor. */
outb(SEL_RESET_CMD, ioaddr);
/* We are supposed to wait for 2 us after a SEL_RESET */
@@ -675,7+702,7 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev) SLOW_DOWN_IO;
/* Do I also need to flush the transmit buffers here? YES? */
- lp->tx_start = lp->tx_end = RCV_RAM;
+ lp->tx_start = lp->tx_end = rcv_ram;
lp->tx_last = 0;
dev->tbusy=0;
@@ -722,7+749,7 @@ static void eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
- int ioaddr, status, boguscount = 0;
+ int ioaddr, status, boguscount = 20;
if (net_debug > 5)
printk("eepro: entering eepro_interrupt routine.\n");
@@ -737,7+764,7 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
do {
status = inb(ioaddr + STATUS_REG);
-
+
if (status & RX_INT) {
if (net_debug > 4)
printk("eepro: packet received interrupt.\n");
@@ -748,6+775,7 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs) /* Get the received packets */
eepro_rx(dev);
}
+
else if (status & TX_INT) {
if (net_debug > 4)
printk("eepro: packet transmit interrupt.\n");
@@ -757,10+785,9 @@ eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* Process the status of transmitted packets */
eepro_transmit_interrupt(dev);
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
- } while ((++boguscount < 10) && (status & 0x06));
+ }
+
+ } while ((boguscount-- > 0) && (status & 0x06));
dev->interrupt = 0;
if (net_debug > 5)
@@ -774,6+801,7 @@ eepro_close(struct device *dev) {
struct eepro_local *lp = (struct eepro_local *)dev->priv;
int ioaddr = dev->base_addr;
+ int rcv_ram = dev->mem_end;
short temp_reg;
dev->tbusy = 1;
@@ -789,7+817,7 @@ eepro_close(struct device *dev)
/* Flush the Tx and disable Rx. */
outb(STOP_RCV_CMD, ioaddr);
- lp->tx_start = lp->tx_end = RCV_RAM ;
+ lp->tx_start = lp->tx_end = rcv_ram ;
lp->tx_last = 0;
/* Mask all the interrupts. */
@@ -912,7+940,9 @@ set_multicast_list(struct device *dev) outw(status | CHAIN_BIT, ioaddr + IO_PORT);
lp->tx_end = i ;
}
- else lp->tx_start = lp->tx_end = i ;
+ else {
+ lp->tx_start = lp->tx_end = i ;
+ }
/* Acknowledge that the MC setup is done */
do { /* We should be doing this in the eepro_interrupt()! */
@@ -993,13+1023,25 @@ hardware_send_packet(struct device *dev, void *buf, short length) {
struct eepro_local *lp = (struct eepro_local *)dev->priv;
short ioaddr = dev->base_addr;
- unsigned status, tx_available, last, end, boguscount = 10;
+ int rcv_ram = dev->mem_end;
+ unsigned status, tx_available, last, end, boguscount = 100;
if (net_debug > 5)
printk("eepro: entering hardware_send_packet routine.\n");
while (boguscount-- > 0) {
+ /* Disable RX and TX interrupts. Necessary to avoid
+ corruption of the HOST_ADDRESS_REG by interrupt
+ service routines. */
+ outb(ALL_MASK, ioaddr + INT_MASK_REG);
+
+ if (dev->interrupt == 1) {
+ /* Enable RX and TX interrupts */
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+ continue;
+ }
+
/* determine how much of the transmit buffer space is available */
if (lp->tx_end > lp->tx_start)
tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
@@ -1007,14+1049,15 @@ hardware_send_packet(struct device *dev, void *buf, short length) tx_available = lp->tx_start - lp->tx_end;
else tx_available = XMT_RAM;
- /* Disable RX and TX interrupts. Necessary to avoid
- corruption of the HOST_ADDRESS_REG by interrupt
- service routines. */
- outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER)
>= tx_available) /* No space available ??? */
+ {
+ eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
+
+ /* Enable RX and TX interrupts */
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
continue;
+ }
last = lp->tx_end;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
@@ -1023,10+1066,10 @@ hardware_send_packet(struct device *dev, void *buf, short length) if ((RAM_SIZE - last) <= XMT_HEADER) {
/* Arrrr!!!, must keep the xmt header together,
several days were lost to chase this one down. */
- last = RCV_RAM;
+ last = rcv_ram;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
}
- else end = RCV_RAM + (end - RAM_SIZE);
+ else end = rcv_ram + (end - RAM_SIZE);
}
outw(last, ioaddr + HOST_ADDRESS_REG);
@@ -1044,9+1087,17 @@ hardware_send_packet(struct device *dev, void *buf, short length) outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
}
- if (lp->tx_start != lp->tx_end) {
+ /* A dummy read to flush the DRAM write pipeline */
+ status = inw(ioaddr + IO_PORT);
+
+ if (lp->tx_start == lp->tx_end) {
+ outw(last, ioaddr + XMT_BAR);
+ outb(XMT_CMD, ioaddr);
+ lp->tx_start = last; /* I don't like to change tx_start here */
+ }
+ else {
/* update the next address and the chain bit in the
- last packet */
+ last packet */
if (lp->tx_end != last) {
outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
outw(last, ioaddr + IO_PORT);
@@ -1054,33+1105,26 @@ hardware_send_packet(struct device *dev, void *buf, short length) outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
status = inw(ioaddr + IO_PORT);
outw(status | CHAIN_BIT, ioaddr + IO_PORT);
- }
- /* A dummy read to flush the DRAM write pipeline */
- status = inw(ioaddr + IO_PORT);
-
- /* Enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
-
- if (lp->tx_start == lp->tx_end) {
- outw(last, ioaddr + XMT_BAR);
- outb(XMT_CMD, ioaddr);
- lp->tx_start = last; /* I don't like to change tx_start here */
+ /* Continue the transmit command */
+ outb(RESUME_XMT_CMD, ioaddr);
}
- else outb(RESUME_XMT_CMD, ioaddr);
lp->tx_last = last;
lp->tx_end = end;
+ /* Enable RX and TX interrupts */
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+
if (dev->tbusy) {
dev->tbusy = 0;
- mark_bh(NET_BH);
}
if (net_debug > 5)
printk("eepro: exiting hardware_send_packet routine.\n");
return;
}
+
dev->tbusy = 1;
if (net_debug > 5)
printk("eepro: exiting hardware_send_packet routine.\n");
@@ -1090,7+1134,7 @@ static void eepro_rx(struct device *dev)
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
- short ioaddr = dev->base_addr;
+ short ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
short boguscount = 20;
short rcv_car = lp->rx_start;
unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
@@ -1171,7+1215,7 @@ eepro_transmit_interrupt(struct device *dev) {
struct eepro_local *lp = (struct eepro_local *)dev->priv;
short ioaddr = dev->base_addr;
- short boguscount = 10;
+ short boguscount = 20;
short xmt_status;
while (lp->tx_start != lp->tx_end) {
@@ -1179,16+1223,15 @@ eepro_transmit_interrupt(struct device *dev) outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
xmt_status = inw(ioaddr+IO_PORT);
if ((xmt_status & TX_DONE_BIT) == 0) break;
+
xmt_status = inw(ioaddr+IO_PORT);
lp->tx_start = inw(ioaddr+IO_PORT);
-
- if (dev->tbusy) {
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
+
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
if (xmt_status & 0x2000)
- lp->stats.tx_packets++;
+ lp->stats.tx_packets++;
else {
lp->stats.tx_errors++;
if (xmt_status & 0x0400)
@@ -1196,10+1239,12 @@ eepro_transmit_interrupt(struct device *dev) printk("%s: XMT status = %#x\n",
dev->name, xmt_status);
}
- if (xmt_status & 0x000f)
+ if (xmt_status & 0x000f) {
lp->stats.collisions += (xmt_status & 0x000f);
- if ((xmt_status & 0x0040) == 0x0)
+ }
+ if ((xmt_status & 0x0040) == 0x0) {
lp->stats.tx_heartbeat_errors++;
+ }
if (--boguscount == 0)
break;
@@ -1216,6+1261,7 @@ static struct device dev_eepro = {
static int io = 0x200;
static int irq = 0;
+static int mem = (RCV_RAM/1024); /* Size of the rx buffer in KB */
int
init_module(void)
@@ -1224,6+1270,7 @@ init_module(void) printk("eepro: You should not use auto-probing with insmod!\n");
dev_eepro.base_addr = io;
dev_eepro.irq = irq;
+ dev_eepro.mem_end = mem;
if (register_netdev(&dev_eepro) != 0)
return -EIO;
@@ -873,9+873,9 @@ plip_rebuild_header(void *buff, struct device *dev, unsigned long dst, return 0;
}
- for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++)
+ for (i=0; i < ETH_ALEN - sizeof(u32); i++)
eth->h_dest[i] = 0xfc;
- memcpy(&(eth->h_dest[i]), &dst, sizeof(unsigned long));
+ *(u32 *)(eth->h_dest+i) = dst;
return 0;
}
@@ -964,9+964,9 @@ plip_open(struct device *dev) nl->is_deferred = 0;
/* Fill in the MAC-level header. */
- for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++)
+ for (i=0; i < ETH_ALEN - sizeof(u32); i++)
dev->dev_addr[i] = 0xfc;
- memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(unsigned long));
+ *(u32 *)(dev->dev_addr+i) = dev->pa_addr;
dev->interrupt = 0;
dev->start = 1;
/* fdomain.c -- Future Domain TMC-16x0 SCSI driver
* Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Thu Apr 4 20:44:47 1996 by r.faith@ieee.org
+ * Revised: Thu Aug 8 14:58:51 1996 by r.faith@ieee.org
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
*
- * $Id: fdomain.c,v 5.41 1996/04/05 04:22:25 root Exp $
+ * $Id: fdomain.c,v 5.44 1996/08/08 18:58:53 root Exp $
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
1.3.34 5.39 12 Oct 1995 V3.60 BIOS; /proc
1.3.72 5.39 8 Feb 1996 Adaptec AHA-2920 board
1.3.85 5.41 4 Apr 1996
+ 2.0.12 5.44 8 Aug 1996 Use ID 7 for all PCI cards
@@ -275,7+276,7 @@ struct proc_dir_entry proc_scsi_fdomain = { S_IFDIR | S_IRUGO | S_IXUGO, 2
};
-#define VERSION "$Revision: 5.41 $"
+#define VERSION "$Revision: 5.44 $"
/* START OF USER DEFINABLE OPTIONS */
@@ -580,8+581,8 @@ static int fdomain_is_valid_port( int port )
/* Try to toggle 32-bit mode. This only
works on an 18c30 chip. (User reports
- say that this doesn't work at all, so
- we'll use the other method.) */
+ say this works, so we should switch to
+ it in the near future.) */
outb( 0x80, port + IO_Control );
if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
@@ -1018,7+1019,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) tpnt->this_id = (this_id & 0x07);
adapter_mask = (1 << tpnt->this_id);
} else {
- if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
+ if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
tpnt->this_id = 7;
adapter_mask = 0x80;
} else {
@@ -1246,7+1247,7 @@ static int fdomain_select( int target ) #endif
#if ERRORS_ONLY
if (!target) {
- if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */
+ if (!flag) /* Skip first failure for all chips. */
++flag;
else
printk( "fdomain: Selection failed\n" );
@@ -1394,7+1395,9 @@ void fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs ) printk( "Status = %x, ", current_SC->SCp.Status );
#endif
#if ERRORS_ONLY
- if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
+ if (current_SC->SCp.Status
+ && current_SC->SCp.Status != 2
+ && current_SC->SCp.Status != 8) {
printk( "fdomain: target = %d, command = %x, status = %x\n",
current_SC->target,
current_SC->cmnd[0],
@@ -1666,7+1669,7 @@ void fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs ) qualifier = (unsigned char)(*((char *)current_SC->request_buffer
+ 13));
- if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
+ if (key != UNIT_ATTENTION
&& !(key == NOT_READY
&& code == 0x04
&& (!qualifier || qualifier == 0x02 || qualifier == 0x01))
@@ -261,6+261,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #ifdef CONFIG_SCSI_QLOGIC_FAS
QLOGICFAS,
#endif
+#ifdef CONFIG_SCSI_QLOGIC_ISP
+ QLOGICISP,
+#endif
#ifdef CONFIG_SCSI_PAS16
MV_PAS16,
#endif
@@ -294,9+297,6 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #ifdef CONFIG_SCSI_AM53C974
AM53C974,
#endif
-#ifdef CONFIG_SCSI_QLOGIC_ISP
- QLOGICISP,
-#endif
#ifdef CONFIG_SCSI_PPA
PPA,
#endif
@@ -490,6+490,9 @@ static void do_sd_request (void) if( SDev->removable && !intr_count )
{
scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
+ /* scsi_ioctl may allow CURRENT to change, so start over. */
+ SDev->was_reset = 0;
+ continue;
}
SDev->was_reset = 0;
}
@@ -485,11+485,11 @@ void sr_photocd(struct inode *inode) printk(KERN_WARNING"sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
break; /* if the first ioctl fails, we don't call the second one */
}
+ is_xa = (rec[0] == 0x20);
min = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16;
sec = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
frame = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
- is_xa = (rec[0] == 0x20) || sector;
if (sector) {
sector -= CD_BLOCK_OFFSET;
#ifdef DEBUG
@@ -566,9+566,6 @@ void sr_photocd(struct inode *inode) break;
}
sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
- if (rec[6] <= 1) {
- sector = 0; /* ignore sector offsets from first track */
- }
is_xa = !!sector;
#ifdef DEBUG
if (sector)
@@ -629,7+629,7 @@ ess_audio_prepare_for_input (int dev, int bsize, int bcount)
if (devc->channels == 1)
{
- if (devc->bits == AFMT_U8 == 0)
+ if (devc->bits == AFMT_U8)
{ /* 8 bit mono */
ess_write (devc, 0xb7, 0x51);
ess_write (devc, 0xb7, 0xd0);
@@ -87,6+87,7 @@ sb_midi_close (int dev) sb_dsp_reset (devc);
devc->intr_active = 0;
devc->input_opened = 0;
+ devc->opened = 0;
restore_flags (flags);
}
@@ -289,7+289,7 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma) size, dmap->bytes_in_use);
}
- if (remap_page_range (vma_get_start (vma), virt_to_phys(dmap->raw_buf),
+ if (remap_page_range (vma_get_start (vma), (unsigned long)dmap->raw_buf,
vma_get_end (vma) - vma_get_start (vma),
vma_get_page_prot (vma)))
return -EAGAIN;
@@ -765,7+765,7 @@ do_load_elf_library(int fd){
/* First of all, some simple consistency checks */
if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
- (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
+ !elf_check_arch(elf_ex.e_machine) ||
(!inode->i_op || !inode->i_op->default_file_ops->mmap))
return -ENOEXEC;
@@ -1101,7+1101,7 @@ static inline void after_unlock_page (struct page * page) if (clear_bit(PG_decr_after, &page->flags))
atomic_dec(&nr_async_pages);
if (clear_bit(PG_free_after, &page->flags))
- free_page(page_address(page));
+ __free_page(page);
if (clear_bit(PG_swap_unlock_after, &page->flags))
swap_after_unlock_page(page->swap_unlock_entry);
}
@@ -1322,11+1322,10 @@ bad_count: */
int generic_readpage(struct inode * inode, struct page * page)
{
- unsigned long block, address;
+ unsigned long block;
int *p, nr[PAGE_SIZE/512];
int i;
- address = page_address(page);
page->count++;
set_bit(PG_locked, &page->flags);
set_bit(PG_free_after, &page->flags);
@@ -1342,7+1341,7 @@ int generic_readpage(struct inode * inode, struct page * page) } while (i > 0);
/* IO start */
- brw_page(READ, address, inode->i_dev, nr, inode->i_sb->s_blocksize, 1);
+ brw_page(READ, page_address(page), inode->i_dev, nr, inode->i_sb->s_blocksize, 1);
return 0;
}
*
* Bruno Haible : remove 4K limit for the maps file
* <haible@ma2s2.mathematik.uni-karlsruhe.de>
+ *
+ * Yves Arrouye : remove removal of trailing spaces in get_array.
+ * <Yves.Arrouye@marin.fdn.fr>
*/
#include <linux/types.h>
@@ -370,7+373,7 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long for (;;) {
addr = get_phys_addr(*p, start);
if (!addr)
- goto ready;
+ return result;
do {
c = *(char *) addr;
if (!c)
@@ -378,17+381,13 @@ static int get_array(struct task_struct ** p, unsigned long start, unsigned long if (size < PAGE_SIZE)
buffer[size++] = c;
else
- goto ready;
+ return result;
addr++;
start++;
if (!c && start >= end)
- goto ready;
+ return result;
} while (addr & ~PAGE_MASK);
}
-ready:
- /* remove the trailing blanks, used to fill out argv,envp space */
- while (result>0 && buffer[result-1]==' ')
- result--;
return result;
}
@@ -967,7+967,7 @@ static void do_mount_root(void) #ifdef CONFIG_BLK_DEV_FD
if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
floppy_eject();
-#ifdef CONFIG_BLK_DEV_RAM
+#ifndef CONFIG_BLK_DEV_RAM
printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
#endif
printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
@@ -38,4+38,15 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; memcpy((char *) &_dest, (char *) &_dump.regs, \
sizeof(elf_gregset_t)); }
+/* $0 is set by ld.so to a pointer to a function which might be
+ registered using atexit. This provides a mean for the dynamic
+ linker to call DT_FINI functions for shared libraries that have
+ been loaded before the code runs.
+
+ So that we can use the same startup file with static executables,
+ we start programs with a value of 0 to indicate that there is no
+ such function. */
+
+#define ELF_PLAT_INIT(_r) _r->r0 = 0
+
#endif
@@ -17,17+17,46 @@ typedef struct user_m68kfp_struct elf_fpregset_t; /*
* This is used to ensure we don't load something for the wrong architecture.
*/
-#define elf_check_arch(x) ((x) == EM_M68K)
+#define elf_check_arch(x) ((x) == EM_68K)
/*
* These are used to set parameters in the core dumps.
- * FIXME(eric) I don't know what the correct endianness to use is.
*/
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB;
-#define ELF_ARCH EM_M68K
+#define ELF_ARCH EM_68K
+
+ /* For SVR4/m68k the function pointer to be registered with
+ `atexit' is passed in %a1. Although my copy of the ABI has
+ no such statement, it is actually used on ASV. */
+#define ELF_PLAT_INIT(_r) _r->a1 = 0
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
+#define ELF_CORE_COPY_REGS(pr_reg, regs) \
+ /* Bleech. */ \
+ pr_reg[0] = regs->d1; \
+ pr_reg[1] = regs->d2; \
+ pr_reg[2] = regs->d3; \
+ pr_reg[3] = regs->d4; \
+ pr_reg[4] = regs->d5; \
+ pr_reg[7] = regs->a0; \
+ pr_reg[8] = regs->a1; \
+ pr_reg[14] = regs->d0; \
+ pr_reg[15] = rdusp(); \
+ pr_reg[16] = 0; /* orig_d0 */ \
+ pr_reg[17] = regs->sr; \
+ pr_reg[18] = regs->pc; \
+ { \
+ struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \
+ pr_reg[5] = sw->d6; \
+ pr_reg[6] = sw->d7; \
+ pr_reg[9] = sw->a2; \
+ pr_reg[10] = sw->a3; \
+ pr_reg[11] = sw->a4; \
+ pr_reg[12] = sw->a5; \
+ pr_reg[13] = sw->a6; \
+ }
+
#endif
+/*
+ * These are the public elements of the Linux kernel AX.25 code. A similar
+ * file netrom.h exists for the NET/ROM protocol.
+ */
+
+#ifndef AX25_KERNEL_H
+#define AX25_KERNEL_H
+
#define PF_AX25 AF_AX25
#define AX25_MTU 256
-#define AX25_MAX_DIGIS 6
-
-typedef struct
-{
- char ax25_call[7]; /* 6 call + SSID (shifted ascii!) */
-}
-ax25_address;
-
-struct sockaddr_ax25
-{
- short sax25_family;
- ax25_address sax25_call;
- int sax25_ndigis;
- /* Digipeater ax25_address sets follow */
-};
-
-#define sax25_uid sax25_ndigis
-
-struct full_sockaddr_ax25
-{
- struct sockaddr_ax25 fsa_ax25;
- ax25_address fsa_digipeater[AX25_MAX_DIGIS];
-};
-
-struct ax25_routes_struct
-{
- ax25_address port_addr;
- ax25_address dest_addr;
- unsigned char digi_count;
- ax25_address digi_addr[AX25_MAX_DIGIS];
-};
-
-struct ax25_route_opt_struct
-{
- ax25_address port_addr;
- ax25_address dest_addr;
- int cmd;
- int arg;
-};
-
-struct ax25_ctl_struct
-{
- ax25_address port_addr;
- ax25_address source_addr;
- ax25_address dest_addr;
- unsigned int cmd;
- unsigned long arg;
-};
-
-struct ax25_bpqaddr_struct
-{
- char dev[16];
- ax25_address addr;
-};
+#define AX25_MAX_DIGIS 6 /* This is wrong, should be 8 */
#define AX25_WINDOW 1
#define AX25_T1 2
@@ -79,16+34,8 @@ struct ax25_bpqaddr_struct #define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7)
#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8)
-#define AX25_SET_RT_PERMANENT 1
#define AX25_SET_RT_IPMODE 2
-#define AX25_RT_DYNAMIC 0
-#define AX25_RT_PERMANENT 1
-
-#define AX25_RT_IPMODE_DEFAULT ' '
-#define AX25_RT_IPMODE_DATAGRAM 'D'
-#define AX25_RT_IPMODE_VC 'V'
-
#define AX25_NOUID_DEFAULT 0
#define AX25_NOUID_BLOCK 1
@@ -113,8+60,54 @@ struct ax25_bpqaddr_struct #define AX25_VALUES_IPMAXQUEUE 15 /* Maximum number of buffers enqueued */
#define AX25_MAX_VALUES 20
-struct ax25_parms_struct
-{
+typedef struct {
+ char ax25_call[7]; /* 6 call + SSID (shifted ascii!) */
+} ax25_address;
+
+struct sockaddr_ax25 {
+ short sax25_family;
+ ax25_address sax25_call;
+ int sax25_ndigis;
+ /* Digipeater ax25_address sets follow */
+};
+
+#define sax25_uid sax25_ndigis
+
+struct full_sockaddr_ax25 {
+ struct sockaddr_ax25 fsa_ax25;
+ ax25_address fsa_digipeater[AX25_MAX_DIGIS];
+};
+
+struct ax25_routes_struct {
+ ax25_address port_addr;
+ ax25_address dest_addr;
+ unsigned char digi_count;
+ ax25_address digi_addr[AX25_MAX_DIGIS];
+};
+
+struct ax25_route_opt_struct {
+ ax25_address port_addr;
+ ax25_address dest_addr;
+ int cmd;
+ int arg;
+};
+
+struct ax25_ctl_struct {
+ ax25_address port_addr;
+ ax25_address source_addr;
+ ax25_address dest_addr;
+ unsigned int cmd;
+ unsigned long arg;
+};
+
+struct ax25_bpqaddr_struct {
+ char dev[16];
+ ax25_address addr;
+};
+
+struct ax25_parms_struct {
ax25_address port_addr;
unsigned short values[AX25_MAX_VALUES];
};
+
+#endif
@@ -38,7+38,6 @@ typedef unsigned long Elf32_Word; #define EM_88K 5
#define EM_486 6 /* Perhaps disused */
#define EM_860 7
-#define EM_PPC 20
#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */
@@ -116,6+116,9 @@ struct vm_operations_struct { * is used for linear searches (eg. clock algorithm scans).
*/
typedef struct page {
+ /* these must be first (free area handling) */
+ struct page *next;
+ struct page *prev;
struct inode *inode;
unsigned long offset;
struct page *next_hash;
@@ -124,8+127,6 @@ typedef struct page { unsigned dirty:16,
age:8;
struct wait_queue *wait;
- struct page *next;
- struct page *prev;
struct page *prev_hash;
struct buffer_head * buffers;
unsigned long swap_unlock_entry;
@@ -247,6+248,7 @@ extern inline unsigned long get_free_page(int priority)
#define free_page(addr) free_pages((addr),0)
extern void free_pages(unsigned long addr, unsigned long order);
+extern void __free_page(struct page *);
extern void show_free_areas(void);
extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
+/*
+ * These are the public elements of the Linux kernel NET/ROM implementation.
+ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
+ * definition of the ax25_address structure.
+ */
+
+#ifndef NETROM_KERNEL_H
+#define NETROM_KERNEL_H
+
#define PF_NETROM AF_NETROM
#define NETROM_MTU 236
@@ -45,3+54,5 @@ struct nr_ctl_struct { unsigned int cmd;
unsigned long arg;
};
+
+#endif
#define AX25_DEF_N2 10
#define AX25_DEF_IDLE 20
#define AX25_DEF_PACLEN 256
-#define AX25_DEF_IPMAXQUEUE 1 /* 1 * ax25->window */
+#define AX25_DEF_IPMAXQUEUE 2 /* 1 * ax25->window */
#define AX25_DEF_DIGI (AX25_DIGI_INBAND|AX25_DIGI_XBAND)
typedef struct ax25_uid_assoc {
@@ -203,15+203,13 @@ extern void dama_check_need_response(ax25_cb *, int, int); /* dl1bke 960114 */ extern void dama_establish_data_link(ax25_cb *);
/* ax25_route.c */
-extern void ax25_rt_rx_frame(ax25_address *, struct device *, ax25_digi *);
extern int ax25_rt_get_info(char *, char **, off_t, int, int);
extern int ax25_cs_get_info(char *, char **, off_t, int, int);
extern int ax25_rt_autobind(ax25_cb *, ax25_address *);
-extern void ax25_rt_build_path(ax25_cb *, ax25_address *);
+extern void ax25_rt_build_path(ax25_cb *, ax25_address *, struct device *);
extern void ax25_dg_build_path(struct sk_buff *, ax25_address *, struct device *);
extern void ax25_rt_device_down(struct device *);
extern int ax25_rt_ioctl(unsigned int, void *);
-extern void ax25_ip_mode_set(ax25_address *, struct device *, char);
extern char ax25_ip_mode_get(ax25_address *, struct device *);
extern unsigned short ax25_dev_get_value(struct device *, int);
extern void ax25_dev_device_up(struct device *);
@@ -64,10+64,21 @@ typedef struct { struct sock *sk; /* Backlink to socket */
} nr_cb;
+struct nr_neigh {
+ struct nr_neigh *next;
+ ax25_address callsign;
+ ax25_digi *digipeat;
+ struct device *dev;
+ unsigned char quality;
+ unsigned char locked;
+ unsigned short count;
+ unsigned int number;
+};
+
struct nr_route {
- unsigned char quality;
- unsigned char obs_count;
- unsigned short neighbour;
+ unsigned char quality;
+ unsigned char obs_count;
+ struct nr_neigh *neighbour;
};
struct nr_node {
@@ -79,17+90,6 @@ struct nr_node { struct nr_route routes[3];
};
-struct nr_neigh {
- struct nr_neigh *next;
- ax25_address callsign;
- ax25_digi *digipeat;
- struct device *dev;
- unsigned char quality;
- unsigned char locked;
- unsigned short count;
- unsigned short number;
-};
-
/* af_netrom.c */
extern struct nr_parms_struct nr_default;
extern int nr_rx_frame(struct sk_buff *, struct device *);
@@ -78,7+78,7 @@ void invalidate_inode_pages(struct inode * inode) page->prev = NULL;
remove_page_from_hash_queue(page);
page->inode = NULL;
- free_page(page_address(page));
+ __free_page(page);
continue;
}
}
@@ -111,15+111,16 @@ repeat: page->prev = NULL;
remove_page_from_hash_queue(page);
page->inode = NULL;
- free_page(page_address(page));
+ __free_page(page);
continue;
}
p = &page->next;
offset = start - offset;
/* partial truncate, clear end of page */
if (offset < PAGE_SIZE) {
- memset((void *) (offset + page_address(page)), 0, PAGE_SIZE - offset);
- flush_page_to_ram(page_address(page));
+ unsigned long address = page_address(page);
+ memset((void *) (offset + address), 0, PAGE_SIZE - offset);
+ flush_page_to_ram(address);
}
}
}
@@ -175,7+176,7 @@ int shrink_mmap(int priority, int dma) if (page->inode) {
remove_page_from_hash_queue(page);
remove_page_from_inode_queue(page);
- free_page(page_address(page));
+ __free_page(page);
return 1;
}
@@ -36,30+36,34 @@ int nr_free_pages = 0;
#define NR_MEM_LISTS 6
+/* The start of this MUST match the start of "struct page" */
struct free_area_struct {
- struct page list;
+ struct page *next;
+ struct page *prev;
unsigned int * map;
};
+#define memory_head(x) ((struct page *)x)
+
static struct free_area_struct free_area[NR_MEM_LISTS];
-static inline void init_mem_queue(struct page * head)
+static inline void init_mem_queue(struct free_area_struct * head)
{
- head->next = head;
- head->prev = head;
+ head->next = memory_head(head);
+ head->prev = memory_head(head);
}
-static inline void add_mem_queue(struct page * head, struct page * entry)
+static inline void add_mem_queue(struct free_area_struct * head, struct page * entry)
{
struct page * next = head->next;
- entry->prev = head;
+ entry->prev = memory_head(head);
entry->next = next;
next->prev = entry;
head->next = entry;
}
-static inline void remove_mem_queue(struct page * head, struct page * entry)
+static inline void remove_mem_queue(struct page * entry)
{
struct page * next = entry->next;
struct page * prev = entry->prev;
@@ -85,9+89,12 @@ static inline void remove_mem_queue(struct page * head, struct page * entry)
/*
* Buddy system. Hairy. You really aren't expected to understand this
+ *
+ * Hint: -mask = 1+~mask
*/
static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
{
+ struct free_area_struct *area = free_area + order;
unsigned long index = map_nr >> (1 + order);
unsigned long mask = (~0UL) << order;
unsigned long flags;
@@ -98,23+105,32 @@ static inline void free_pages_ok(unsigned long map_nr, unsigned long order) #define list(x) (mem_map+(x))
map_nr &= mask;
- nr_free_pages += 1 << order;
- while (order < NR_MEM_LISTS-1) {
- if (!change_bit(index, free_area[order].map))
+ nr_free_pages -= mask;
+ while (mask + (1 << (NR_MEM_LISTS-1))) {
+ if (!change_bit(index, area->map))
break;
- remove_mem_queue(&free_area[order].list, list(map_nr ^ (1+~mask)));
+ remove_mem_queue(list(map_nr ^ -mask));
mask <<= 1;
- order++;
+ area++;
index >>= 1;
map_nr &= mask;
}
- add_mem_queue(&free_area[order].list, list(map_nr));
+ add_mem_queue(area, list(map_nr));
#undef list
restore_flags(flags);
}
+void __free_page(struct page *page)
+{
+ if (!PageReserved(page) && atomic_dec_and_test(&page->count)) {
+ unsigned long map_nr = page->map_nr;
+ delete_from_swap_cache(map_nr);
+ free_pages_ok(map_nr, 0);
+ }
+}
+
void free_pages(unsigned long addr, unsigned long order)
{
unsigned long map_nr = MAP_NR(addr);
@@ -141,8+157,8 @@ void free_pages(unsigned long addr, unsigned long order) #define RMQUEUE(order, dma) \
do { struct free_area_struct * area = free_area+order; \
unsigned long new_order = order; \
- do { struct page *prev = &area->list, *ret; \
- while (&area->list != (ret = prev->next)) { \
+ do { struct page *prev = memory_head(area), *ret; \
+ while (memory_head(area) != (ret = prev->next)) { \
if (!dma || CAN_DMA(ret)) { \
unsigned long map_nr = ret->map_nr; \
(prev->next = ret->next)->prev = prev; \
@@ -162,7+178,7 @@ do { struct free_area_struct * area = free_area+order; \ do { unsigned long size = 1 << high; \
while (high > low) { \
area--; high--; size >>= 1; \
- add_mem_queue(&area->list, map); \
+ add_mem_queue(area, map); \
MARK_USED(index, high, area); \
index += size; \
map += size; \
@@ -219,7+235,7 @@ void show_free_areas(void) for (order=0 ; order < NR_MEM_LISTS; order++) {
struct page * tmp;
unsigned long nr = 0;
- for (tmp = free_area[order].list.next ; tmp != &free_area[order].list ; tmp = tmp->next) {
+ for (tmp = free_area[order].next ; tmp != memory_head(free_area+order) ; tmp = tmp->next) {
nr ++;
}
total += nr * ((PAGE_SIZE>>10) << order);
@@ -269,7+285,7 @@ unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)
for (i = 0 ; i < NR_MEM_LISTS ; i++) {
unsigned long bitmap_size;
- init_mem_queue(&free_area[i].list);
+ init_mem_queue(free_area+i);
mask += mask;
end_mem = (end_mem + ~mask) & mask;
bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
/*
- * AX.25 release 031
+ * AX.25 release 032
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* AX.25 032 Joerg(DL1BKE) Fixed DAMA timeout error.
* ax25_send_frame() limits the number of enqueued
* datagrams per socket.
+ * Jonathan(G4KLX) Remove auto-router.
*
* To do:
* Restructure the ax25_rcv code to be cleaner/faster and
* The null address is defined as a callsign of all spaces with an
* SSID of zero.
*/
-ax25_address null_ax25_address = {{0x40,0x40,0x40,0x40,0x40,0x40,0x00}};
+ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
ax25_cb *volatile ax25_list = NULL;
@@ -137,8+138,7 @@ char *ax2asc(ax25_address *a) char c, *s;
int n;
- for (n = 0, s = buf; n < 6; n++)
- {
+ for (n = 0, s = buf; n < 6; n++) {
c = (a->ax25_call[n] >> 1) & 0x7F;
if (c != ' ') *s++ = c;
@@ -146,8+146,7 @@ char *ax2asc(ax25_address *a)
*s++ = '-';
- if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9)
- {
+ if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
*s++ = '1';
n -= 10;
}
@@ -492,6+491,7 @@ static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) return a->uid;
}
return -ENOENT;
+
case SIOCAX25ADDUID:
if(!suser())
return -EPERM;
@@ -505,8+505,8 @@ static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) a->next = ax25_uid_list;
ax25_uid_list = a;
return 0;
- case SIOCAX25DELUID:
- {
+
+ case SIOCAX25DELUID: {
ax25_uid_assoc **l;
if(!suser())
@@ -524,6+524,9 @@ static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) }
return -ENOENT;
}
+
+ default:
+ return -EINVAL;
}
return -EINVAL; /*NOTREACHED */
@@ -673,7+676,7 @@ static ax25_cb *ax25_create_cb(void)
init_timer(&ax25->timer);
- ax25->dama_slave = 0; /* dl1bke 951121 */
+ ax25->dama_slave = 0;
ax25->rtt = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
ax25->t1 = AX25_DEF_T1 * PR_SLOWHZ;
@@ -705,6+708,7 @@ static ax25_cb *ax25_create_cb(void) } else {
ax25->window = AX25_DEF_WINDOW;
}
+
ax25->device = NULL;
ax25->digipeat = NULL;
ax25->sk = NULL;
@@ -789,7+793,7 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest, } else {
ax25_output(ax25, skb);
}
- ax25->idletimer = ax25->idle; /* dl1bke 960228 */
+ ax25->idletimer = ax25->idle;
return 1; /* It already existed */
}
}
@@ -809,10+813,10 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest, }
*ax25->digipeat = *digi;
} else {
- ax25_rt_build_path(ax25, dest);
+ ax25_rt_build_path(ax25, dest, dev);
}
- if (ax25_dev_is_dama_slave(ax25->device)) /* dl1bke 960116 */
+ if (ax25_dev_is_dama_slave(ax25->device))
dama_establish_data_link(ax25);
else
ax25_establish_data_link(ax25);
@@ -1208,7+1212,6 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev) return NULL;
}
- /* dl1bke 960119: we have to copy the old digipeater list! */
*ax25->digipeat = *osk->ax25->digipeat;
}
@@ -1414,10+1417,6 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, }
sk->ax25->digipeat->lastrepeat = 0;
- } else { /* dl1bke 960117 */
- if (sk->debug)
- printk("building digipeater path\n");
- ax25_rt_build_path(sk->ax25, &addr->sax25_call);
}
/*
@@ -1548,7+1547,6 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
- ax25_address *addr;
struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
struct sock *sk;
unsigned char ndigi, i;
@@ -1558,25+1556,30 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, if (peer != 0) {
if (sk->state != TCP_ESTABLISHED)
return -ENOTCONN;
- addr = &sk->ax25->dest_addr;
+
+ sax->fsa_ax25.sax25_family = AF_AX25;
+ sax->fsa_ax25.sax25_call = sk->ax25->dest_addr;
+ sax->fsa_ax25.sax25_ndigis = 0;
+ *uaddr_len = sizeof(struct full_sockaddr_ax25);
+
+ if (sk->ax25->digipeat != NULL) {
+ ndigi = sk->ax25->digipeat->ndigi;
+ sax->fsa_ax25.sax25_ndigis = ndigi;
+ for (i = 0; i < ndigi; i++)
+ sax->fsa_digipeater[i] = sk->ax25->digipeat->calls[i];
+ }
} else {
- addr = &sk->ax25->source_addr;
+ sax->fsa_ax25.sax25_family = AF_AX25;
+ sax->fsa_ax25.sax25_call = sk->ax25->source_addr;
+ sax->fsa_ax25.sax25_ndigis = 1;
+ *uaddr_len = sizeof(struct full_sockaddr_ax25);
+
+ if (sk->ax25->device != NULL)
+ memcpy(&sax->fsa_digipeater[0], sk->ax25->device->dev_addr, AX25_ADDR_LEN);
+ else
+ sax->fsa_digipeater[0] = null_ax25_address;
}
- sax->fsa_ax25.sax25_family = AF_AX25;
- sax->fsa_ax25.sax25_call = *addr;
- sax->fsa_ax25.sax25_ndigis = 0;
- *uaddr_len = sizeof(struct sockaddr_ax25);
-
- /* This will supply digipeat path on both getpeername() and getsockname() */
- if (sk->ax25->digipeat != NULL) {
- ndigi = sk->ax25->digipeat->ndigi;
- sax->fsa_ax25.sax25_ndigis = ndigi;
- *uaddr_len += AX25_ADDR_LEN * ndigi;
- for (i = 0; i < ndigi; i++)
- sax->fsa_digipeater[i] = sk->ax25->digipeat->calls[i];
- }
-
return 0;
}
@@ -1615,13+1618,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a }
/*
- * Send the frame to the AX.25 auto-router
- */
-#ifdef notdef /* dl1bke 960310 */
- ax25_rt_rx_frame(&src, dev, &dp);
-#endif
-
- /*
* Ours perhaps ?
*/
if (dp.lastrepeat + 1 < dp.ndigi) { /* Not yet digipeated completely */
@@ -1653,8+1649,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a return 0;
}
- ax25_rt_rx_frame(&src, dev, &dp);
-
build_ax25_addr(skb->data, &src, &dest, &dp, type, MODULUS);
#ifdef CONFIG_FIREWALL
if (call_fw_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) {
@@ -1702,14+1696,11 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a switch (skb->data[1]) {
#ifdef CONFIG_INET
case AX25_P_IP:
- ax25_rt_rx_frame(&src, dev, &dp);
skb_pull(skb,2); /* drop PID/CTRL */
- ax25_ip_mode_set(&src, dev, 'D');
ip_rcv(skb, dev, ptype); /* Note ptype here is the wrong one, fix me later */
break;
case AX25_P_ARP:
- ax25_rt_rx_frame(&src, dev, &dp);
skb_pull(skb,2);
arp_rcv(skb, dev, ptype); /* Note ptype here is wrong... */
break;
@@ -1720,7+1711,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a if (sk->rmem_alloc >= sk->rcvbuf) {
kfree_skb(skb, FREE_READ);
} else {
- ax25_rt_rx_frame(&src, dev, &dp);
/*
* Remove the control and PID.
*/
@@ -1764,7+1754,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a * free it immediately. This routine itself wakes the user context layers so we
* do no further work
*/
- ax25_rt_rx_frame(&src, dev, &dp);
if (ax25_process_rx_frame(ax25, skb, type, dama) == 0)
kfree_skb(skb, FREE_READ);
@@ -1790,7+1779,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a /* b) received SABM(E) */
if ((sk = ax25_find_listener(&dest, dev, SOCK_SEQPACKET)) != NULL) {
- ax25_rt_rx_frame(&src, dev, &dp);
if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, dev)) == NULL) {
if (mine)
ax25_return_dm(dev, &src, &dest, &dp);
@@ -1815,8+1803,6 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a return 0;
}
- ax25_rt_rx_frame(&src, dev, &dp);
-
if ((ax25 = ax25_create_cb()) == NULL) {
ax25_return_dm(dev, &src, &dest, &dp);
kfree_skb(skb, FREE_READ);
@@ -1826,10+1812,8 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a ax25_fillin_cb(ax25, dev);
ax25->idletimer = ax25->idle;
#else
- if (mine) {
- ax25_rt_rx_frame(&src, dev, &dp);
+ if (mine)
ax25_return_dm(dev, &src, &dest, &dp);
- }
kfree_skb(skb, FREE_READ);
return 0;
@@ -1882,7+1866,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
if (sk != NULL) {
if (!sk->dead)
- sk->data_ready(sk, skb->len );
+ sk->data_ready(sk, skb->len);
} else {
kfree_skb(skb, FREE_READ);
}
@@ -1944,13+1928,12 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no ax25_digi *dp;
ax25_digi dtmp;
int lv;
- int addr_len=msg->msg_namelen;
+ int addr_len = msg->msg_namelen;
- if (sk->err) {
+ if (sk->err)
return sock_error(sk);
- }
- if (flags|| msg->msg_control)
+ if (flags || msg->msg_control)
return -EINVAL;
if (sk->zapped)
@@ -2079,9+2062,8 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n int er;
int dama;
- if (sk->err) {
+ if (sk->err)
return sock_error(sk);
- }
if (addr_len != NULL)
*addr_len = sizeof(*sax);
@@ -2176,8+2158,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) put_fs_long(amount, (unsigned long *)arg);
return 0;
- case TIOCINQ:
- {
+ case TIOCINQ: {
struct sk_buff *skb;
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
@@ -2201,8+2182,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */
case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */
- case SIOCAX25GETUID:
- {
+ case SIOCAX25GETUID: {
struct sockaddr_ax25 sax25;
if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct sockaddr_ax25))) != 0)
return err;
@@ -2303,7+2283,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i ax25->window,
ax25->paclen);
- len += sprintf(buffer + len, " %s", ax25->dama_slave? " slave" : " no");
+ len += sprintf(buffer + len, " %s", ax25->dama_slave ? " slave" : " no");
if (ax25->sk != NULL) {
len += sprintf(buffer + len, " %5d %5d\n",
@@ -2434,7+2414,6 @@ void ax25_proto_init(struct net_proto *pro) * A small shim to dev_queue_xmit to handle the difference between
* KISS AX.25 and BPQ AX.25.
*/
-
void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
{
unsigned char *ptr;
@@ -2449,8+2428,8 @@ void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) skb->protocol = htons (ETH_P_AX25);
#ifdef CONFIG_BPQETHER
- if(dev->type == ARPHRD_ETHER) {
- static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ if (dev->type == ARPHRD_ETHER) {
+ static char bcast_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
int size;
if(skb_headroom(skb) < AX25_BPQ_HEADER_LEN) {
@@ -2546,8+2525,7 @@ int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long des
if (bp[16] == AX25_P_IP) {
mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
- if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V'))
- {
+ if (mode == 'V' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
/*
* This is a workaround to try to keep the device locking
* straight until skb->free=0 is abolished post 1.4.
@@ -2593,7+2571,6 @@ int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long des * dl1bke 960317: we use ax25_queue_xmit here to allow mode datagram
* over ethernet. I don't know if this is valid, though.
*/
-
ax25_dg_build_path(skb, (ax25_address *)(bp + 1), dev);
ax25_queue_xmit(skb, dev, SOPRI_NORMAL);
/*
- * AX.25 release 031
+ * AX.25 release 032
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* Joerg(DL1BKE) Renamed it to "IDLE" with a slightly
* different behaviour. Fixed defrag
* routine (I hope)
+ * AX.25 032 Jonathan(G4KLX) Remove auto-router.
+ * Darryl(G7LED) AX.25 segmentation fixed.
*/
#include <linux/config.h>
@@ -70,66+72,57 @@ static int ax25_rx_iframe(ax25_cb *, struct sk_buff *); static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
{
struct sk_buff *skbn, *skbo;
- int hdrlen;
+ int hdrlen, nhdrlen;
if (ax25->fragno != 0) {
if (!(*skb->data & SEG_FIRST)) {
if ((ax25->fragno - 1) == (*skb->data & SEG_REM)) {
-
- /* enqueue fragment */
-
+ /* Enqueue fragment */
ax25->fragno = *skb->data & SEG_REM;
skb_pull(skb, 1); /* skip fragno */
ax25->fraglen += skb->len;
skb_queue_tail(&ax25->frag_queue, skb);
-
- /* last fragment received? */
+ /* Last fragment received ? */
if (ax25->fragno == 0) {
- if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL)
- return 0;
+ if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL) {
+ while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+ kfree_skb(skbo, FREE_READ);
+ return 1;
+ }
skbn->free = 1;
skbn->arp = 1;
- skbn->dev = skb->dev;
+ skbn->dev = ax25->device;
if (ax25->sk != NULL) {
skbn->sk = ax25->sk;
atomic_add(skbn->truesize, &ax25->sk->rmem_alloc);
}
- /* get first fragment from queue */
-
+ skb_reserve(skbn, AX25_MAX_HEADER_LEN);
+
+ /* Get first fragment from queue */
skbo = skb_dequeue(&ax25->frag_queue);
- hdrlen = skbo->data - skbo->h.raw - 2; /* skip PID & fragno */
-
- skb_push(skbo, hdrlen + 2); /* start of address field */
- skbn->data = skb_put(skbn, hdrlen); /* get space for info */
- memcpy(skbn->data, skbo->data, hdrlen); /* copy address field */
- skb_pull(skbo, hdrlen + 2); /* start of data */
- skb_pull(skbn, hdrlen + 1); /* ditto */
+ hdrlen = skbo->data - skbo->h.raw;
+ nhdrlen = hdrlen - 2;
- /* copy data from first fragment */
+ skb_push(skbo, hdrlen);
+ skb_push(skbn, nhdrlen);
+ skbn->h.raw = skbn->data;
- memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
- kfree_skb(skbo, FREE_READ);
-
- /* add other fragment's data */
+ /* Copy AX.25 headers */
+ memcpy(skbn->data, skbo->data, nhdrlen);
+ skb_pull(skbn, nhdrlen);
+ skb_pull(skbo, hdrlen);
- while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
+ /* Copy data from the fragments */
+ do {
memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
kfree_skb(skbo, FREE_READ);
- }
+ } while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL);
- ax25->fraglen = 0; /* reset counter */
-
- /*
- * mysteriously we need to re-adjust skb->data.
- * Anyway, it seems to work. Do we have the address fields
- * encoded TWICE in one sk_buff?
- */
-
- skb_pull(skbn, hdrlen);
+ ax25->fraglen = 0;
if (ax25_rx_iframe(ax25, skbn) == 0)
kfree_skb(skbn, FREE_READ);
@@ -139,9+132,10 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb) }
}
} else {
- /* first fragment received? */
-
+ /* First fragment received */
if (*skb->data & SEG_FIRST) {
+ while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+ kfree_skb(skbo, FREE_READ);
ax25->fragno = *skb->data & SEG_REM;
skb_pull(skb, 1); /* skip fragno */
ax25->fraglen = skb->len;
@@ -181,7+175,6 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb) case AX25_P_IP:
skb_pull(skb, 1); /* Remove PID */
skb->h.raw = skb->data;
- ax25_ip_mode_set(&ax25->dest_addr, ax25->device, 'V');
ip_rcv(skb, ax25->device, NULL); /* Wrong ptype */
queued = 1;
break;
@@ -273,7+266,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype break;
default:
- if (dama && pf) /* dl1bke 960116 */
+ if (dama && pf)
ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
break;
}
@@ -490,7+483,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype }
if (ax25->condition & OWN_RX_BUSY_CONDITION) {
if (pf) {
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_enquiry_response(ax25);
@@ -498,20+491,21 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype break;
}
if (ns == ax25->vr) {
+ ax25->vr = (ax25->vr + 1) % ax25->modulus;
queued = ax25_rx_iframe(ax25, skb);
if (ax25->condition & OWN_RX_BUSY_CONDITION) {
+ ax25->vr = ns; /* ax25->vr - 1 */
if (pf) {
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_enquiry_response(ax25);
}
break;
}
- ax25->vr = (ax25->vr + 1) % ax25->modulus;
ax25->condition &= ~REJECT_CONDITION;
if (pf) {
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_enquiry_response(ax25);
@@ -524,14+518,14 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype } else {
if (ax25->condition & REJECT_CONDITION) {
if (pf) {
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_enquiry_response(ax25);
}
} else {
ax25->condition |= REJECT_CONDITION;
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_send_control(ax25, REJ, pf, C_RESPONSE);
@@ -660,7+654,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
case RR:
ax25->condition &= ~PEER_RX_BUSY_CONDITION;
- if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+ if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
ax25->t1timer = 0;
if (ax25_validate_nr(ax25, nr)) {
ax25_frames_acked(ax25, nr);
@@ -691,7+685,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
case REJ:
ax25->condition &= ~PEER_RX_BUSY_CONDITION;
- if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+ if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
ax25->t1timer = 0;
if (ax25_validate_nr(ax25, nr)) {
ax25_frames_acked(ax25, nr);
@@ -735,7+729,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype }
ax25_frames_acked(ax25, nr);
if (ax25->condition & OWN_RX_BUSY_CONDITION) {
- if (pf) { /* dl1bke 960114 */
+ if (pf) {
if (ax25->dama_slave)
ax25_enquiry_response(ax25);
else
@@ -744,9+738,11 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype break;
}
if (ns == ax25->vr) {
+ ax25->vr = (ax25->vr + 1) % ax25->modulus;
queued = ax25_rx_iframe(ax25, skb);
if (ax25->condition & OWN_RX_BUSY_CONDITION) {
- if (pf) { /* dl1bke 960114 */
+ ax25->vr = ns; /* ax25->vr - 1 */
+ if (pf) {
if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
@@ -754,10+750,9 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype }
break;
}
- ax25->vr = (ax25->vr + 1) % ax25->modulus;
ax25->condition &= ~REJECT_CONDITION;
if (pf) {
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_enquiry_response(ax25);
@@ -769,7+764,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype }
} else {
if (ax25->condition & REJECT_CONDITION) {
- if (pf) { /* dl1bke 960114 */
+ if (pf) {
if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
@@ -777,7+772,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype }
} else {
ax25->condition |= REJECT_CONDITION;
- if (ax25->dama_slave) /* dl1bke 960114 */
+ if (ax25->dama_slave)
dama_enquiry_response(ax25);
else
ax25_send_control(ax25, REJ, pf, C_RESPONSE);
/*
- * AX.25 release 031
+ * AX.25 release 032
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* AX.25 030 Jonathan(G4KLX) Added fragmentation to ax25_output.
* Added support for extended AX.25.
* AX.25 031 Joerg(DL1BKE) Added DAMA support
- *
* Joerg(DL1BKE) Modified fragmenter to fragment vanilla
* AX.25 I-Frames. Added PACLEN parameter.
* Joerg(DL1BKE) Fixed a problem with buffer allocation
@@ -214,7+213,7 @@ void ax25_kick(ax25_cb *ax25) do {
if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
skb_queue_head(&ax25->write_queue, skb);
- return;
+ break;
}
next = (ax25->vs + 1) % ax25->modulus;
/*
- * AX.25 release 031
+ * AX.25 release 032
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* Joerg(DL1BKE) Fixed AX.25 routing of IP datagram and VC, new ioctl()
* "SIOCAX25OPTRT" to set IP mode and a 'permanent' flag
* on routes.
+ * AX.25 032 Jonathan(G4KLX) Remove auto-router.
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
-#define AX25_ROUTE_MAX 128
-
static struct ax25_route {
struct ax25_route *next;
ax25_address callsign;
struct device *dev;
ax25_digi *digipeat;
- struct timeval stamp;
- int n;
char ip_mode;
- char perm;
} *ax25_route = NULL;
static struct ax25_dev {
@@ -82,120+78,22 @@ static struct ax25_dev { unsigned short values[AX25_MAX_VALUES];
} *ax25_device = NULL;
-static struct ax25_route * ax25_find_route(ax25_address *addr);
+static struct ax25_route *ax25_find_route(ax25_address *, struct device *);
/*
* small macro to drop non-digipeated digipeaters and reverse path
*/
-
static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
{
int k;
+
for (k = 0; k < in->ndigi; k++)
if (!in->repeated[k])
break;
- in->ndigi = k;
- ax25_digi_invert(in, out);
-
-}
-
-/*
- * dl1bke 960310: new behaviour:
- *
- * * try to find an existing route to 'src', if found:
- * - if the route was added manually don't adjust the timestamp
- * - if this route is 'permanent' just do some statistics and return
- * - overwrite device and digipeater path
- * * no existing route found:
- * - try to alloc a new entry
- * - overwrite the oldest, not manually added entry if this fails.
- *
- * * updated on reception of frames directed to us _only_
- *
- */
-
-void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
-{
- unsigned long flags;
- extern struct timeval xtime;
- struct ax25_route *ax25_rt;
- struct ax25_route *oldest;
- int count;
-
- count = 0;
- oldest = NULL;
-
- for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
- if (count == 0 || oldest->stamp.tv_sec == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
- oldest = ax25_rt;
-
- if (ax25cmp(&ax25_rt->callsign, src) == 0) {
- if (ax25_rt->stamp.tv_sec != 0)
- ax25_rt->stamp = xtime;
-
- if (ax25_rt->perm == AX25_RT_PERMANENT) {
- ax25_rt->n++;
- return;
- }
-
- ax25_rt->dev = dev;
- if (digi == NULL) {
- /* drop old digipeater list */
- if (ax25_rt->digipeat != NULL) {
- kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
- ax25_rt->digipeat = NULL;
- }
- return;
- }
-
- if (ax25_rt->digipeat == NULL && (ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
- return;
-
- ax25_route_invert(digi, ax25_rt->digipeat);
- return;
- }
-
- count++;
- }
-
- if (count > AX25_ROUTE_MAX) {
- if (oldest->stamp.tv_sec == 0)
- return;
- if (oldest->digipeat != NULL)
- kfree_s(oldest->digipeat, sizeof(ax25_digi));
- ax25_rt = oldest;
- } else {
- if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
- return; /* No space */
- }
-
- ax25_rt->callsign = *src;
- ax25_rt->dev = dev;
- ax25_rt->digipeat = NULL;
- ax25_rt->stamp = xtime;
- ax25_rt->n = 1;
- ax25_rt->ip_mode = ' ';
- ax25_rt->perm = AX25_RT_DYNAMIC;
-
- if (digi != NULL) {
- if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
- kfree_s(ax25_rt, sizeof(struct ax25_route));
- return;
- }
-
- ax25_route_invert(digi, ax25_rt->digipeat);
- /* used to be: *ax25_rt->digipeat = *digi; */
- }
-
- if (ax25_rt != oldest) {
- save_flags(flags);
- cli();
- ax25_rt->next = ax25_route;
- ax25_route = ax25_rt;
+ in->ndigi = k;
- restore_flags(flags);
- }
+ ax25_digi_invert(in, out);
}
void ax25_rt_device_down(struct device *dev)
@@ -261,7+159,6 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
}
- ax25_rt->stamp.tv_sec = 0;
return 0;
}
}
@@ -270,10+167,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) ax25_rt->callsign = route.dest_addr;
ax25_rt->dev = dev;
ax25_rt->digipeat = NULL;
- ax25_rt->stamp.tv_sec = 0;
- ax25_rt->n = 0;
ax25_rt->ip_mode = ' ';
- ax25_rt->perm = AX25_RT_DYNAMIC;
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
kfree_s(ax25_rt, sizeof(struct ax25_route));
@@ -323,40+217,36 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) }
}
break;
+
case SIOCAX25OPTRT:
if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0)
return err;
memcpy_fromfs(&rt_option, arg, sizeof(rt_option));
if ((dev = ax25rtr_get_dev(&rt_option.port_addr)) == NULL)
return -EINVAL;
- ax25_rt = ax25_route;
- while (ax25_rt != NULL) {
+ for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25_rt->dev == dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) {
- switch(rt_option.cmd) {
- case AX25_SET_RT_PERMANENT:
- ax25_rt->perm = (char) rt_option.arg;
- ax25_rt->stamp.tv_sec = 0;
- break;
+ switch (rt_option.cmd) {
case AX25_SET_RT_IPMODE:
switch (rt_option.arg) {
- case AX25_RT_IPMODE_DEFAULT:
- ax25_rt->ip_mode = ' ';
- break;
- case AX25_RT_IPMODE_DATAGRAM:
- ax25_rt->ip_mode = 'D';
- break;
- case AX25_RT_IPMODE_VC:
- ax25_rt->ip_mode = 'V';
+ case ' ':
+ case 'D':
+ case 'V':
+ ax25_rt->ip_mode = rt_option.arg;
break;
default:
return -EINVAL;
}
break;
+ default:
+ return -EINVAL;
}
}
- ax25_rt = ax25_rt->next;
}
break;
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -373,26+263,22 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d
cli();
- len += sprintf(buffer, "callsign dev count time mode F digipeaters\n");
+ len += sprintf(buffer, "callsign dev mode digipeaters\n");
for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
callsign = "default";
else
callsign = ax2asc(&ax25_rt->callsign);
- len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
+ len += sprintf(buffer + len, "%-9s %-4s",
callsign,
- ax25_rt->dev ? ax25_rt->dev->name : "???",
- ax25_rt->n,
- ax25_rt->stamp.tv_sec);
+ ax25_rt->dev ? ax25_rt->dev->name : "???");
switch (ax25_rt->ip_mode) {
case 'V':
- case 'v':
len += sprintf(buffer + len, " vc");
break;
case 'D':
- case 'd':
len += sprintf(buffer + len, " dg");
break;
default:
@@ -400,20+286,6 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d break;
}
- switch (ax25_rt->perm) {
- case AX25_RT_DYNAMIC:
- if (ax25_rt->stamp.tv_sec == 0)
- len += sprintf(buffer + len, " M");
- else
- len += sprintf(buffer + len, " ");
- break;
- case AX25_RT_PERMANENT:
- len += sprintf(buffer + len, " P");
- break;
- default:
- len += sprintf(buffer + len, " ?");
- }
-
if (ax25_rt->digipeat != NULL)
for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
@@ -479,8+351,7 @@ int ax25_cs_get_info(char *buffer, char **start, off_t offset, int length, int d /*
* Find AX.25 route
*/
-
-static struct ax25_route * ax25_find_route(ax25_address *addr)
+static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev)
{
struct ax25_route *ax25_spe_rt = NULL;
struct ax25_route *ax25_def_rt = NULL;
@@ -491,10+362,17 @@ static struct ax25_route * ax25_find_route(ax25_address *addr) * route if none is found;
*/
for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
- if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
- ax25_spe_rt = ax25_rt;
- if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
- ax25_def_rt = ax25_rt;
+ if (dev == NULL) {
+ if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
+ ax25_spe_rt = ax25_rt;
+ if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
+ ax25_def_rt = ax25_rt;
+ } else {
+ if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)
+ ax25_spe_rt = ax25_rt;
+ if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)
+ ax25_def_rt = ax25_rt;
+ }
}
if (ax25_spe_rt != NULL)
@@ -508,7+386,6 @@ static struct ax25_route * ax25_find_route(ax25_address *addr) * a target on the digipeater path but w/o having a special route
* set before, the path has to be truncated from your target on.
*/
-
static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
{
int k;
@@ -530,14+407,14 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) struct ax25_route *ax25_rt;
ax25_address *call;
- if ((ax25_rt = ax25_find_route(addr)) == NULL)
+ if ((ax25_rt = ax25_find_route(addr, NULL)) == NULL)
return -EHOSTUNREACH;
+ ax25->device = ax25_rt->dev;
+
if ((call = ax25_findbyuid(current->euid)) == NULL) {
if (ax25_uid_policy && !suser())
return -EPERM;
- if (ax25->device == NULL)
- return -ENODEV;
call = (ax25_address *)ax25->device->dev_addr;
}
@@ -560,19+437,20 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) * dl1bke 960117: build digipeater path
* dl1bke 960301: use the default route if it exists
*/
-void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr)
+void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev)
{
struct ax25_route *ax25_rt;
- ax25_rt = ax25_find_route(addr);
+ if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
+ return;
- if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+ if (ax25_rt->digipeat == NULL)
return;
if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
return;
- ax25->device = ax25_rt->dev;
+ ax25->device = ax25_rt->dev;
*ax25->digipeat = *ax25_rt->digipeat;
ax25_adjust_path(addr, ax25->digipeat);
}
@@ -587,8+465,10 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
skb_pull(skb, 1); /* skip KISS command */
- ax25_rt = ax25_find_route(addr);
- if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+ if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
+ return;
+
+ if (ax25_rt->digipeat == NULL)
return;
digipeat = *ax25_rt->digipeat;
@@ -611,22+491,6 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device * }
/*
- * Register the mode of an incoming IP frame. It is assumed that an entry
- * already exists in the routing table.
- */
-void ax25_ip_mode_set(ax25_address *callsign, struct device *dev, char ip_mode)
-{
- struct ax25_route *ax25_rt;
-
- for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
- if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev) {
- ax25_rt->ip_mode = ip_mode;
- return;
- }
- }
-}
-
-/*
* Return the IP mode of a given callsign/device pair.
*/
char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
@@ -908,6+772,9 @@ int ax25_bpq_ioctl(unsigned int cmd, void *arg) ax25_bpqdev = bpqdev;
restore_flags(flags);
break;
+
+ default:
+ return -EINVAL;
}
return 0;
/*
- * AX.25 release 031
+ * AX.25 release 032
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
@@ -101,7+101,7 @@ void ax25_frames_acked(ax25_cb *ax25, unsigned short nr) skb->free = 1;
kfree_skb(skb, FREE_WRITE);
ax25->va = (ax25->va + 1) % ax25->modulus;
- if (ax25->dama_slave) /* dl1bke 960120 */
+ if (ax25->dama_slave)
ax25->n2count = 0;
}
}
/*
- * AX.25 release 031
+ * AX.25 release 032
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
@@ -113,7+113,7 @@ static void ax25_timer(unsigned long param) if (ax25->sk != NULL) {
if (ax25->sk->rmem_alloc < (ax25->sk->rcvbuf / 2) && (ax25->condition & OWN_RX_BUSY_CONDITION)) {
ax25->condition &= ~OWN_RX_BUSY_CONDITION;
- if (!ax25->dama_slave) /* dl1bke */
+ if (!ax25->dama_slave)
ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
ax25->condition &= ~ACK_PENDING_CONDITION;
break;
@@ -123,7+123,7 @@ static void ax25_timer(unsigned long param) * Check for frames to transmit.
*/
if (!ax25->dama_slave)
- ax25_kick(ax25); /* dl1bke 960114 */
+ ax25_kick(ax25);
break;
default:
@@ -134,7+134,7 @@ static void ax25_timer(unsigned long param) if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
if (ax25->condition & ACK_PENDING_CONDITION) {
ax25->condition &= ~ACK_PENDING_CONDITION;
- if (!ax25->dama_slave) /* dl1bke 960114 */
+ if (!ax25->dama_slave)
ax25_timeout_response(ax25);
}
}
@@ -272,7+272,7 @@ void ax25_t1_timeout(ax25_cb * ax25) #endif
ax25_clear_queues(ax25);
ax25->state = AX25_STATE_0;
- ax25_send_control(ax25, DISC, POLLON, C_COMMAND); /* dl1bke */
+ ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
if (ax25->sk != NULL) {
ax25->sk->state = TCP_CLOSE;
@@ -283,14+283,14 @@ void ax25_t1_timeout(ax25_cb * ax25) }
} else {
ax25->n2count++;
- if (!ax25_dev_is_dama_slave(ax25->device)) /* dl1bke */
+ if (!ax25_dev_is_dama_slave(ax25->device))
ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
}
break;
case AX25_STATE_3:
ax25->n2count = 1;
- if (!ax25->dama_slave) /* dl1bke 960114 */
+ if (!ax25->dama_slave)
ax25_transmit_enquiry(ax25);
ax25->state = AX25_STATE_4;
break;
@@ -314,7+314,7 @@ void ax25_t1_timeout(ax25_cb * ax25) }
} else {
ax25->n2count++;
- if (!ax25->dama_slave) /* dl1bke 960114 */
+ if (!ax25->dama_slave)
ax25_transmit_enquiry(ax25);
}
break;
@@ -315,7+315,7 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, #endif
IS_SKB(skb);
- if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF))
+ if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF)))
{
ip_statistics.IpFragFails++;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
@@ -645,7+645,7 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i * Check for any "DF" flag. [DF means do not fragment]
*/
- if (ntohs(iph->frag_off) & IP_DF)
+ if (iph->frag_off & htons(IP_DF))
{
ip_statistics.IpFragFails++;
NETDEBUG(printk("ip_queue_xmit: frag needed\n"));
@@ -279,7+279,7 @@ void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk) /*
* Wait up to 1 second for the buffer to fill.
*/
- sk->partial_timer.expires = jiffies+HZ;
+ sk->partial_timer.expires = jiffies+HZ/10;
sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial;
sk->partial_timer.data = (unsigned long) sk;
add_timer(&sk->partial_timer);
@@ -966,6+966,10 @@ void tcp_send_ack(struct sock *sk) sock_wfree(sk, buff);
return;
}
+#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
+ buff->ip_hdr->frag_off |= htons(IP_DF);
+#endif
+
t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
/*
@@ -934,7+934,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, sax->fsa_ax25.sax25_ndigis = 1;
sax->fsa_ax25.sax25_call = sk->nr->user_addr;
sax->fsa_digipeater[0] = sk->nr->dest_addr;
- *uaddr_len = sizeof(struct sockaddr_ax25) + AX25_ADDR_LEN;
+ *uaddr_len = sizeof(struct full_sockaddr_ax25);
} else {
sax->fsa_ax25.sax25_family = AF_NETROM;
sax->fsa_ax25.sax25_ndigis = 0;
@@ -952,14+952,13 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev) ax25_address *src, *dest, *user;
unsigned short circuit_index, circuit_id;
unsigned short frametype, window, timeout;
-
skb->sk = NULL; /* Initially we don't know who it's for */
/*
* skb->data points to the netrom frame start
*/
-
+
src = (ax25_address *)(skb->data + 0);
dest = (ax25_address *)(skb->data + 7);
@@ -1327,7+1326,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int
cli();
- len += sprintf(buffer, "user_addr dest_node src_node dev my your st vs vr va t1 t2 n2 rtt wnd paclen Snd-Q Rcv-Q\n");
+ len += sprintf(buffer, "user_addr dest_node src_node dev my your st vs vr va t1 t2 n2 rtt wnd paclen Snd-Q Rcv-Q\n");
for (s = nr_list; s != NULL; s = s->next) {
if ((dev = s->nr->device) == NULL)
@@ -1339,7+1338,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length, int ax2asc(&s->nr->user_addr));
len += sprintf(buffer + len, "%-9s ",
ax2asc(&s->nr->dest_addr));
- len += sprintf(buffer + len, "%-9s %-3s %02X/%02X %02X/%02X %2d %2d %2d %2d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
+ len += sprintf(buffer + len, "%-9s %-3s %02X/%02X %02X/%02X %2d %3d %3d %3d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
ax2asc(&s->nr->source_addr),
devname, s->nr->my_index, s->nr->my_id,
s->nr->your_index, s->nr->your_id,
@@ -168,7+168,7 @@ void nr_kick(struct sock *sk) do {
if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
skb_queue_head(&sk->write_queue, skb);
- return;
+ break;
}
next = (sk->nr->vs + 1) % NR_MODULUS;
* NET/ROM 001 Jonathan(G4KLX) First attempt.
* NET/ROM 003 Jonathan(G4KLX) Use SIOCADDRT/SIOCDELRT ioctl values
* for NET/ROM routes.
+ * Use '*' for a blank mnemonic in /proc/net/nr_nodes.
+ * Change default quality for new neighbour when same
+ * as node callsign.
* Alan Cox(GW4PTS) Added the firewall hooks.
- *
- * TO DO
- * Sort out the which pointer when shuffling entries in the routes
- * section. Also reset the which pointer when a route becomes "good"
- * again, ie when a NODES broadcast is processed via calls to
- * nr_add_node().
*/
#include <linux/config.h>
#include <linux/firewall.h>
#include <net/netrom.h>
-static int nr_neigh_no = 1;
+static unsigned int nr_neigh_no = 1;
static int nr_route_on = 1;
static struct nr_node *nr_node_list = NULL;
static struct nr_neigh *nr_neigh_list = NULL;
+static void nr_remove_neigh(struct nr_neigh *);
+
/*
* Add a new route to a node, and in the process add the node and the
* neighbour if it is new.
@@ -72,7+71,10 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 struct nr_route nr_route;
unsigned long flags;
int i, found;
-
+
+ if (nr_dev_get(nr) != NULL) /* Can't add routes to ourself */
+ return -EINVAL;
+
for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
if (ax25cmp(nr, &nr_node->callsign) == 0)
break;
@@ -91,7+93,10 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 nr_neigh->callsign = *ax25;
nr_neigh->digipeat = NULL;
nr_neigh->dev = dev;
- nr_neigh->quality = nr_default.quality;
+ if (ax25cmp(nr, ax25) == 0)
+ nr_neigh->quality = quality;
+ else
+ nr_neigh->quality = nr_default.quality;
nr_neigh->locked = 0;
nr_neigh->count = 0;
nr_neigh->number = nr_neigh_no++;
@@ -118,14+123,14 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 return -ENOMEM;
nr_node->callsign = *nr;
- memcpy(&nr_node->mnemonic, mnemonic, sizeof(nr_node->mnemonic));
+ strcpy(nr_node->mnemonic, mnemonic);
nr_node->which = 0;
nr_node->count = 1;
nr_node->routes[0].quality = quality;
nr_node->routes[0].obs_count = obs_count;
- nr_node->routes[0].neighbour = nr_neigh->number;
+ nr_node->routes[0].neighbour = nr_neigh;
save_flags(flags);
cli();
@@ -138,10+143,13 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 nr_neigh->count++;
return 0;
+ } else {
+ if (nr_node->mnemonic[0] == '\0')
+ strcpy(nr_node->mnemonic, mnemonic);
}
for (found = 0, i = 0; i < nr_node->count; i++) {
- if (nr_node->routes[i].neighbour == nr_neigh->number) {
+ if (nr_node->routes[i].neighbour == nr_neigh) {
nr_node->routes[i].quality = quality;
nr_node->routes[i].obs_count = obs_count;
found = 1;
@@ -157,16+165,22 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
nr_node->routes[0].quality = quality;
nr_node->routes[0].obs_count = obs_count;
- nr_node->routes[0].neighbour = nr_neigh->number;
+ nr_node->routes[0].neighbour = nr_neigh;
+ nr_node->which++;
nr_node->count++;
nr_neigh->count++;
} else {
/* It must be better than the worst */
if (quality > nr_node->routes[2].quality) {
+ nr_node->routes[2].neighbour->count--;
+
+ if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
+ nr_remove_neigh(nr_node->routes[2].neighbour);
+
nr_node->routes[2].quality = quality;
nr_node->routes[2].obs_count = obs_count;
- nr_node->routes[2].neighbour = nr_neigh->number;
+ nr_node->routes[2].neighbour = nr_neigh;
nr_neigh->count++;
}
@@ -212,7+226,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2 }
for (i = 0; i < nr_node->count; i++) {
- if (nr_node->routes[i].neighbour == nr_neigh->number) {
+ if (nr_node->routes[i].neighbour == nr_neigh) {
if (i < nr_node->which)
nr_node->which = i;
break;
@@ -307,7+321,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct d if (nr_neigh == NULL) return -EINVAL;
for (i = 0; i < nr_node->count; i++) {
- if (nr_node->routes[i].neighbour == nr_neigh->number) {
+ if (nr_node->routes[i].neighbour == nr_neigh) {
nr_neigh->count--;
if (nr_neigh->count == 0 && !nr_neigh->locked)
@@ -403,7+417,7 @@ static int nr_del_neigh(ax25_address *callsign, struct device *dev, unsigned int */
static int nr_dec_obs(void)
{
- struct nr_neigh *t, *nr_neigh;
+ struct nr_neigh *nr_neigh;
struct nr_node *s, *nr_node;
int i;
@@ -420,21+434,12 @@ static int nr_dec_obs(void) break;
case 1: /* From 1 -> 0 */
- nr_neigh = nr_neigh_list;
-
- while (nr_neigh != NULL) {
- t = nr_neigh;
- nr_neigh = nr_neigh->next;
-
- if (t->number == s->routes[i].neighbour) {
- t->count--;
+ nr_neigh = s->routes[i].neighbour;
+
+ nr_neigh->count--;
- if (t->count == 0 && !t->locked)
- nr_remove_neigh(t);
-
- break;
- }
- }
+ if (nr_neigh->count == 0 && !nr_neigh->locked)
+ nr_remove_neigh(nr_neigh);
s->count--;
@@ -483,7+488,7 @@ void nr_rt_device_down(struct device *dev) nr_node = nr_node->next;
for (i = 0; i < t->count; i++) {
- if (t->routes[i].neighbour == s->number) {
+ if (t->routes[i].neighbour == s) {
t->count--;
switch (i) {
@@ -609,13+614,16 @@ int nr_rt_ioctl(unsigned int cmd, void *arg)
case SIOCNRDECOBS:
return nr_dec_obs();
-
+
case SIOCNRRTCTL:
if ((err = verify_area(VERIFY_READ, arg, sizeof(int))) != 0)
return err;
opt = get_fs_long((void *)arg);
nr_route_on = opt ? 1 : 0;
return 0;
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -637,7+645,7 @@ void nr_link_failed(ax25_address *callsign, struct device *dev) if (nr_neigh == NULL) return;
for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
- if (nr_node->which >= nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh->number)
+ if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh)
nr_node->which++;
}
@@ -645,7+653,6 @@ void nr_link_failed(ax25_address *callsign, struct device *dev) * Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
* indicates an internally generated frame.
*/
-
int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
{
ax25_address *nr_src, *nr_dest;
@@ -655,12+662,12 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) unsigned char *dptr;
#ifdef CONFIG_FIREWALL
-
- if(ax25 && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+ if (ax25 != NULL && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
return 0;
- if(!ax25 && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+ if (ax25 == NULL && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
return 0;
#endif
+
nr_src = (ax25_address *)(skb->data + 0);
nr_dest = (ax25_address *)(skb->data + 7);
@@ -684,27+691,20 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) if (nr_node == NULL || nr_node->which >= nr_node->count)
return 0;
- for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
- if (nr_neigh->number == nr_node->routes[nr_node->which].neighbour)
- break;
-
- if (nr_neigh == NULL)
- return 0;
+ nr_neigh = nr_node->routes[nr_node->which].neighbour;
if ((dev = nr_dev_first()) == NULL)
return 0;
#ifdef CONFIG_FIREWALL
- if(ax25 && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+ if (ax25 != NULL && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
return 0;
#endif
dptr = skb_push(skb, 1);
*dptr = AX25_P_NETROM;
- ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
-
- return 1;
+ return ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
}
int nr_nodes_get_info(char *buffer, char **start, off_t offset,
@@ -715,7+715,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset, off_t pos = 0;
off_t begin = 0;
int i;
-
+
cli();
len += sprintf(buffer, "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
@@ -723,7+723,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset, for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) {
len += sprintf(buffer + len, "%-9s %-7s %d %d",
ax2asc(&nr_node->callsign),
- nr_node->mnemonic,
+ (nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
nr_node->which + 1,
nr_node->count);
@@ -731,7+731,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset, len += sprintf(buffer + len, " %3d %d %05d",
nr_node->routes[i].quality,
nr_node->routes[i].obs_count,
- nr_node->routes[i].neighbour);
+ nr_node->routes[i].neighbour->number);
}
len += sprintf(buffer + len, "\n");
@@ -742,7+742,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset, len = 0;
begin = pos;
}
-
+
if (pos > offset + length)
break;
}
@@ -754,7+754,7 @@ int nr_nodes_get_info(char *buffer, char **start, off_t offset,
if (len > length) len = length;
- return(len);
+ return len;
}
int nr_neigh_get_info(char *buffer, char **start, off_t offset,
@@ -764,7+764,7 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset, int len = 0;
off_t pos = 0;
off_t begin = 0;
-
+
cli();
len += sprintf(buffer, "addr callsign dev qual lock count\n");
@@ -796,7+796,7 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset,
if (len > length) len = length;
- return(len);
+ return len;
}
#endif