Commit 7388b7aa authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.47

parent 4eeb9af8
......@@ -134,6 +134,12 @@ S: Computer Science Department
S: Baltimore, Maryland 21218
S: USA
N: Axel Boldt
E: boldt@math.ucsb.edu
W: http://math-www.uni-paderborn.de/~axel/
D: Configuration help text support
D: Linux CD and Support Giveaway List
N: John Boyd
E: boyd@cis.ohio-state.edu
D: Co-author of wd7000 SCSI driver
......@@ -214,7 +220,7 @@ S: United Kingdom
N: Ray Dassen
E: jdassen@wi.LeidenUniv.nl
U: http://www.wi.leidenuniv.nl/~jdassen/
W: http://www.wi.leidenuniv.nl/~jdassen/
D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer,
D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels.
S: Zuidsingel 10A
......
# LAST EDIT: Fri Oct 27 23:03:01 1995 by Axel Boldt (boldt@math.ucsb.edu)
# LAST EDIT: Thu Nov 30 22:39:07 1995 by Axel Boldt (boldt@math.ucsb.edu)
#
# This version of the Linux kernel configuration help texts
# corresponds to the kernel versions 1.3.x. Be aware that these
......@@ -9,7 +9,7 @@
#
# Information about what a kernel is, what it does, how to patch and
# compile it and much more is contained in the Kernel-HOWTO, available
# via anonymous ftp from sunsite.unc.edu in the directory
# via ftp (user: anonymous) from sunsite.unc.edu in the directory
# /pub/Linux/docs/HOWTO.
#
# Format: description<nl>variable<nl>helptext<nl><nl>. The help texts
......@@ -21,10 +21,7 @@
# All this was shamelessly stolen from several different sources. Many
# thanks to all the contributors. Feel free to use these help texts
# in your own kernel configuration tools. The texts are copyrighted
# (c) 1995 by Axel Boldt and governed by our beloved little Copyleft
# virus, the GNU Public License. This essentially means that you can
# do with them whatever you want unless you try to restrict someone
# else's right to do whatever they want.
# (c) 1995 by Axel Boldt and governed by the GNU Public License.
#
# Send comments to Axel Boldt <boldt@math.ucsb.edu>.
......@@ -82,26 +79,26 @@ CONFIG_ST506
Use old (reliable) disk-only driver for primary i/f
CONFIG_BLK_DEV_HD
As you might have guessed, there are now two drivers for IDE
harddrives around: the old reliable one and the new improved
one. The new driver can also handle IDE/ATAPI CDROM drives (ATAPI =
AT Attachment Packet Interface is a new protocol currently used for
controlling CDROM and tape drives, similar to the SCSI
protocol. Some newer CDROM drives such as NEC 260 and MITSUMI
triple/quad speed drives use it, but most MITSUMI CDROM drives
don't). The old driver supports up to two hard drives, while the new
one can deal with any mix of up to eight hard drives and IDE/ATAPI
CDROMs, two per IDE interface. Using the old driver makes sense if
you have older MFM/RLL/ESDI drives, since it is smaller and these
drives don't benefit from the additional features of the new
driver. If you have more than one IDE interface (=controller), you
can use the old driver on the first and the new one on the others,
if you like. In that case (or if you have just one interface and
don't want to use the new driver at all) you would say Y here,
thereby enlarging your kernel by about 4 kB. If you want to use the
new driver exclusively, say N and answer Y to the following
question(s). Useful information about how to use large (>504MB) IDE
harddrives is contained in drivers/block/README.ide. If unsure, say
N.
harddrives around: the old one and the new improved one. The old one
is not any longer more reliable than the new one. The new driver can
also handle IDE/ATAPI CDROM drives (ATAPI = AT Attachment Packet
Interface is a new protocol currently used for controlling CDROM and
tape drives, similar to the SCSI protocol. Some newer CDROM drives
such as NEC 260 and MITSUMI triple/quad speed drives use it, but
most MITSUMI CDROM drives don't). The old driver supports up to two
hard drives, while the new one can deal with any mix of up to eight
hard drives and IDE/ATAPI CDROMs, two per IDE interface. Using the
old driver makes sense if you have older MFM/RLL/ESDI drives, since
it is smaller and these drives don't benefit from the additional
features of the new driver. If you have more than one IDE interface
(=controller), you can use the old driver on the first and the new
one on the others, if you like. In that case (or if you have just
one interface and don't want to use the new driver at all) you would
say Y here, thereby enlarging your kernel by about 4 kB. If you want
to use the new driver exclusively, say N and answer Y to the
following question(s). Useful information about how to use large
(>504MB) IDE harddrives is contained in drivers/block/README.ide. If
unsure, say N.
Use new IDE driver for primary/secondary i/f
CONFIG_BLK_DEV_IDE
......@@ -173,11 +170,11 @@ CONFIG_NET
Sun floppy controller support
CONFIG_BLK_DEV_SUNFD
This is support for floppy drives on Sun workstations. But this
support does not exist at this time, so you might as well say N.
This is support for floppy drives on Sun Sparc workstations. Say Y
if you have a floppy drive, otherwise N. Easy.
Alpha system type
CONFIG_ALPHA_JENSEN
CONFIG_ALPHA_AVANTI
Find out what type of Alpha system you are running. If you can't
find one of the given names, then try "Noname". For this question,
it suffices to give a unique prefix of the option you want to
......@@ -204,6 +201,19 @@ CONFIG_ALPHA_SRM
##### Don't know what this is about.
#####
Echo console messages on /dev/ttyS1
CONFIG_SERIAL_ECHO
If you enable this option, all kernel messages that would usually go
to the console will also be sent to the device /dev/ttyS1 which
corresponds to a serial port; this could be useful if you attached
a terminal or printer to that port.
TGA Console Support
CONFIG_TGA_CONSOLE
#####
##### Has something to do with Alpha.
#####
PCI bios support
CONFIG_PCI
Find out whether you have a PCI motherboard. PCI is the name of a
......@@ -216,12 +226,9 @@ CONFIG_PCI
valuable information about which PCI hardware works under Linux and
which doesn't. If some of PCI devices don't work and you get a
warning during boot time, please follow the instructions at the top of
include/linux/pci.h. Information regarding the buggy PCTech RZ 1000 IDE
harddrive controller which is used in some PCI systems is on the WWW
at http://www.powerquest.com/hardware.html. (To browse the WWW, you
need to have access to a machine on the Internet that has one of the
programs lynx, netscape or Mosaic). The new IDE driver detects this
controller and works around this bug, though.
include/linux/pci.h. The buggy PCTech RZ 1000 IDE
harddrive controller which is used in some PCI systems is detected
and correctly handled by this driver.
PCI bridge optimization (experimental)
CONFIG_PCI_OPTIMIZE
......@@ -241,17 +248,19 @@ CONFIG_BLK_DEV_TRITON
System V IPC
CONFIG_SYSVIPC
InterProcessCommunication is a suite of library functions and system
Inter Process Communication is a suite of library functions and system
calls which let processes (= running programs) synchronize and
exchange information. It is generally considered to be a good thing,
and some programs won't run unless you enable this. You can find
documentation about IPC in ipc.info, which is contained in
sunsite.unc.edu:/pub/Linux/docs/man/info.tar.gz (available via ftp,
user: anonymous; extract with "tar xzvf filename"). These docs
are in the info format which is used to document GNU software and
can be read from within emacs ("Ctrl-h i") or with the program info
("man info"). Enabling this option enlarges your kernel by about
7kB. Just say Y.
and some programs won't run unless you enable this. In particular,
if you want to run the DOS emulator dosemu under Linux (read the
DOSEMU-HOWTO, available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/HOWTO), you'll need to say Y here. You
can find documentation about IPC in ipc.info, which is contained in
sunsite.unc.edu:/pub/Linux/docs/man/info.tar.gz (extract with "tar
xzvf filename"). These docs are in the info format which is used to
document GNU software and can be read from within emacs ("Ctrl-h i")
or with the program info ("man info"). Enabling this option enlarges
your kernel by about 7kB. Just say Y.
Kernel support for ELF binaries
CONFIG_BINFMT_ELF
......@@ -291,27 +300,13 @@ CONFIG_KERNEL_ELF
kernel in ELF by saying Y here and editing the variables CC
and LD in the toplevel Makefile.
Use -m486 flag for 486-specific optimizations
Use 486-specific optimizations (does NOT work on i386)
CONFIG_M486
If you have a 486 as opposed to a 386 or Pentium CPU, say Y here:
If you have a 486 or better, as opposed to a 386, say Y here:
things will be slightly faster. However, it is not required: the
kernel will run on all CPUs with and without this option. If you are
not sure, say Y; apart from enlarging your kernel by about 6 kB, it
won't hurt.
SMP Kernel (experimental - gcc2.5.8 only: see Documentation/SMP.txt)
CONFIG_SMP
This is experimental support for multiprocessor Pentium machines
that agree with the Intel MP v1.1 specification. It can deal with up
to 32 processors. You can only compile it with gcc version 2.5.8
("gcc -v"). For details, see Documentation/SMP.ez in the kernel
source (this document has been formatted using the ez andrew word
processor, available via ftp (user: anonymous) from
sunsite.unc.edu:/pub/Linux/X11/andrew/auis63L3-wp.tgz) and
http://www.linux.org.uk/SMP/title.html on the WWW (to browse the
WWW, you need to have access to a machine on the Internet that has
one of the programs lynx, netscape or Mosaic). Please back up all
your harddrives before using kernels compiled with this option.
kernel will run on all CPUs without this option. If you are
not sure, say N; This option will make the kernel use some
instructions that are only available on 486+ machines.
Set version information on all symbols for modules
CONFIG_MODVERSIONS
......@@ -384,8 +379,11 @@ CONFIG_IP_MULTICAST
tables, require that this option be compiled in. You also need
multicasting if you intend to participate in the MBONE, a high
bandwidth network on top of the internet which carries audio and
video broadcasts. Information about the multicast capabilities of
the various network cards is contained in
video broadcasts. More information about the MBONE is on the WWW at
http://www.best.com/~prince/techinfo/mbone.html (to browse the WWW,
you need to have access to a machine on the Internet that has one of
the programs lynx, netscape or Mosaic). Information about the
multicast capabilities of the various network cards is contained in
drivers/net/README.multicast. For most people, it's safe to say N.
IP: firewalling
......@@ -399,13 +397,14 @@ CONFIG_IP_FIREWALL
sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you will have to use
the ipfw tool from the net-tools package, available via ftp (user:
anonymous) from
ftp.linux.org.uk:/pub/linux/Networking/PROGRAMS/NetTools. It allows
selective blocking of internet traffic based on type, origin and
destination. You need to enable IP firewalling in order to be able
to use IP masquerading (i.e. IP traffic from one of the local
computers and destined for an outside host is changed by your box so
that it appears to come from you). Chances are that you don't want
this, so say N.
ftp.linux.org.uk:/pub/linux/Networking/PROGRAMS/NetTools, or
preferably ipfwadm from ftp.xos.nl:/pub/linux/ipfwadm/. These
programs allow selective blocking of internet traffic based on type,
origin and destination. You need to enable IP firewalling in order
to be able to use IP masquerading (i.e. IP traffic from one of the
local computers and destined for an outside host is changed by your
box so that it appears to come from you). Chances are that you don't
want this, so say N.
IP: accounting
CONFIG_IP_ACCT
......@@ -487,7 +486,7 @@ CONFIG_INET_RARP
Since you asked: if there are diskless machines on your network that
know their hardware ethernet address but don't know their IP
addresses upon startup, they send out a Reverse
AddressResolutionProtocol request to find out their own IP
Address Resolution Protocol request to find out their own IP
addresses. If you want your Linux box to be able to *answer* such
requests, say Y here; you'd use the program rarp ("man rarp"). If
you want to compile this as a module ( = code which can be inserted
......@@ -503,13 +502,21 @@ CONFIG_INET_SNARL
links, between machines of your IP network, say N. If in doubt, say
Y.
Disable Path MTU Discovery (normally enabled)
CONFIG_NO_PATH_MTU_DISCOVERY
MTU (maximal transfer unit) is the size of the chunks we send out
over the net. "Path MTU Discovery" means that, instead of always
sending very small chunks, we start out sending big ones and if we
then discover that some host along the way likes its chunks smaller,
we adjust to a smaller size. This is good, so say N.
Disable NAGLE algorithm (normally enabled)
CONFIG_TCP_NAGLE_OFF
The NAGLE algorithm works by requiring an acknowledgment before
sending small IP frames (= packets). This keeps tiny packets from
telnet and rlogin from congesting Wide Area Networks. You may wish
to disable it if you run your X-server from across the network, or
if multiple byte key sequences are delayed. Most people strongly
sending small IP frames (= packets). This keeps tiny telnet and
rlogin packets from congesting Wide Area Networks. You may wish to
disable it if you run your X-server from across the network, or if
multiple byte key sequences are delayed. Most people strongly
recommend to say N here, though, thereby leaving NAGLE enabled.
IP: Drop source routed frames
......@@ -542,17 +549,19 @@ CONFIG_SKB_LARGE
The IPX protocol
CONFIG_IPX
This is support for the Novell networking protocol. You need it if
you want to access Novell Netware servers from within the Linux DOS
emulator dosemu (read the DOSEMU-HOWTO, available via ftp (user:
anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO). It's very
limited and won't make your Linux box into a Novell server. It would
enlarge your kernel by about 5 kB. General information about how to
connect Linux, Windows machines and Macs is on the WWW at
http://eats.com/linux_mac_win.html (to browse the WWW, you need to
have access to a machine on the Internet that has one of the
programs lynx, netscape or Mosaic). Unless you have Novell computers
on your local network, say N.
This is support for the Novell networking protocol, IPX. You need it
if you want to access Novell Netware servers from within the Linux
DOS emulator dosemu (read the DOSEMU-HOWTO, available via ftp (user:
anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO). To
turn your Linux box into a fully featured Netware file server and
IPX router, say Y here and fetch lwared from
sunsite.unc.edu:/pub/Linux/system/Networking/daemons/. General
information about how to connect Linux, Windows machines and Macs is
on the WWW at http://eats.com/linux_mac_win.html (to browse the WWW,
you need to have access to a machine on the Internet that has one of
the programs lynx, netscape or Mosaic). This driver would enlarge
your kernel by about 5 kB. Unless you have Novell computers on your
local network, say N.
Appletalk DDP
CONFIG_ATALK
......@@ -617,22 +626,22 @@ CONFIG_NETROM
Kernel/User network link driver(ALPHA)
CONFIG_NETLINK
This driver will allow for two-way communication between certain
parts of the kernel or modules and user processes; the user
processes will be able to read from and write to special files in
the /dev directory having major mode 18. So far, the kernel uses it
to publish some network related information if you enable "Routing
This driver allows for two-way communication between certain parts
of the kernel or modules and user processes; the user processes are
able to read from and write to character special files in the /dev
directory having major mode 18. So far, the kernel uses it to
publish some network related information if you enable "Routing
messages", below. Say Y if you want to experiment with it; this is
ALPHA code, which means that it need not be completely stable; it
has nothing to do with the computer architecture of the same name.
Routing messages
CONFIG_RTNETLINK
If you enable this and create a special file with major number 18
and minor number 0 with mknod ("man mknod"), you can read some
network related information from that file. Everything you write to
that file will be discarded. Say Y, because otherwise the network
link driver is pointless.
If you enable this and create a character special file /dev/route
with major number 18 and minor number 0 using mknod ("man mknod"),
you can read some network related routing information from that
file. Everything you write to that file will be discarded. Say Y,
because otherwise the network link driver is pointless.
SCSI support?
CONFIG_SCSI
......@@ -752,7 +761,9 @@ CONFIG_SCSI_BUSLOGIC
the documentation in drivers/scsi/README.BusLogic for more information.
BusLogic FlashPoint SCSI Host Adapters are not supported by this driver.
If this driver does not work correctly without modification, please
consult the author. This driver is not currently available as a module.
consult the author. This driver is not currently available as a module.
You might want to read the SCSI-HOWTO, available via ftp (user:
anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO.
EATA-DMA (DPT,NEC&ATT for ISA,EISA,PCI) support
CONFIG_SCSI_EATA_DMA
......@@ -948,7 +959,9 @@ CONFIG_DUMMY
handy, the default is Y. It won't enlarge your kernel either. What a
deal. If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read Documentation/modules.txt.
say M here and read Documentation/modules.txt. If you want to use
more than one dummy device at a time, you need to compile it as a
module.
SLIP (serial line) support
CONFIG_SLIP
......@@ -1334,10 +1347,14 @@ CONFIG_EEXPRESS
If you have a network (ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that the Intel
EtherExpress card is generally regarded to be a very poor choice and
the driver is not very reliable. If you want to compile this as a
module ( = code which can be inserted in and removed from the
running kernel whenever you want), say M here and read
EtherExpress16 card is generally regarded to be a very poor choice
and the driver is not very reliable. (Roger Wolff
(R.E.Wolff@et.tudelft.nl) is attempting to do something about
this. At the moment he could use 1) one or more etherexpress16 cards
to test locally 2) Alpha testers: people to try new versions of the
driver to see if things improve...) If you want to compile this
driver as a module ( = code which can be inserted in and removed
from the running kernel whenever you want), say M here and read
Documentation/modules.txt as well as
Documentation/networking/net-modules.txt. If you plan to use more
than one network card under linux, read the
......@@ -1503,6 +1520,19 @@ CONFIG_DE4X5
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
ICL EtherTeam 16i/32 support
CONFIG_ETH16I
If you have a network (ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is also available
as a module ( = code which can be inserted in and removed from the
running kernel whenever you want). If you want to compile it as a
module, say M here and read Documentation/modules.txt as well as
Documentation/networking/net-modules.txt. If you plan to use more
than one network card under linux, read the
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
Zenith Z-Note support
CONFIG_ZNET
The Zenith Z-Note notebook computer has a built-in network
......@@ -1517,9 +1547,6 @@ CONFIG_NET_POCKET
port ("pocket adaptors"). If you have one of those, say Y and read
the Ethernet-HOWTO, available via ftp (user: anonymous) from
sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than
#####
##### What should you say to CONFIG_PRINTER in order to use these?
#####
one network card under linux, read the Multiple-Ethernet-mini-HOWTO,
available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you
want to plug a network card into the PCMCIA slot of your laptop
......@@ -1530,9 +1557,11 @@ CONFIG_NET_POCKET
will just cause this configure script to skip all the questions
about this class of network devices. If you say Y, you will be
asked for your specific device in the following questions. If you
plan to use more than one network card under linux, read the
plan to use more than one network device under linux, read the
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you intend to use an
adaptor attaching to the parallel port as well as a parallel
printer, you should compile both drivers as modules (if possible).
AT-LAN-TEC/RealTek pocket adaptor support
CONFIG_ATP
......@@ -1542,7 +1571,9 @@ CONFIG_ATP
sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. If
you plan to use more than one network card under linux, read the
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you intend to use
this driver, you should have said N to the Parallel Printer support,
because the two drivers don't like each other.
D-Link DE600 pocket adaptor support
CONFIG_DE600
......@@ -1552,10 +1583,11 @@ CONFIG_DE600
sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. If
you want to compile this as a module ( = code which can be inserted
in and removed from the running kernel whenever you want), say M
here and read Documentation/modules.txt. If you plan to use more
than one network card under linux, read the
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
here and read Documentation/modules.txt. If you intend to use this
pocket adaptor as well as a parallel printer, you should compile
both drivers as modules. If you plan to use more than one network
card under linux, read the Multiple-Ethernet-mini-HOWTO, available
from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
D-Link DE620 pocket adaptor support
CONFIG_DE620
......@@ -1565,10 +1597,11 @@ CONFIG_DE620
sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. If
you want to compile this as a module ( = code which can be inserted
in and removed from the running kernel whenever you want), say M
here and read Documentation/modules.txt. If you plan to use more
than one network card under linux, read the
Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
here and read Documentation/modules.txt. If you intend to use this
pocket adaptor as well as a parallel printer, you should compile
both drivers as modules. If you plan to use more than one network
card under linux, read the Multiple-Ethernet-mini-HOWTO, available
from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
Token Ring driver support
CONFIG_TR
......@@ -1673,17 +1706,17 @@ CONFIG_SBPCD2
Aztech/Orchid/Okano/Wearnes (non IDE) CDROM support
CONFIG_AZTCD
If you have a CDA268-01A, ORCHID CD-3110, OKANO/WEARNES CDD110 CDROM
drive, say Y here and also to "ISO9660 cdrom filesystem support"
below. This is NOT for CDROM drives with IDE interface, such as
Aztech CDA269-031SE. (If you have one of those, you should have said
Y to the new IDE driver above.) You want to read
Documentation/cdrom/aztcd and include/linux/aztcd.h in the kernel
source and the CDROM-HOWTO, available via ftp (user: anonymous) from
sunsite.unc.edu:/pub/Linux/docs/HOWTO. If unsure, say N. If you
want to compile this as a module ( = code which can be inserted in
and removed from the running kernel whenever you want), say M here
and read Documentation/modules.txt.
If you have a CDA268-01A, ORCHID CD-3110, OKANO/WEARNES CDD110 or
Conrad TXC CDROM drive, say Y here and also to "ISO9660 cdrom
filesystem support" below. This is NOT for CDROM drives with IDE
interface, such as Aztech CDA269-031SE. (If you have one of those,
you should have said Y to the new IDE driver above.) You want to
read Documentation/cdrom/aztcd and include/linux/aztcd.h in the
kernel source and the CDROM-HOWTO, available via ftp (user:
anonymous) from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If unsure,
say N. If you want to compile this as a module ( = code which can
be inserted in and removed from the running kernel whenever you
want), say M here and read Documentation/modules.txt.
Sony CDU535 CDROM driver support
CONFIG_CDU535
......@@ -1790,13 +1823,13 @@ CONFIG_EXT2_FS
xiafs filesystem support
CONFIG_XIA_FS
This filesystem (= method to organize files on a harddisk partition
or a floppy disk) is only used rarely these days. This option would
enlarge your kernel by about 28 kB. Say N. If you want to compile
this as a module ( = code which can be inserted in and removed from
the running kernel whenever you want), say M here and read
Documentation/modules.txt. Note that the filesystem of your root
partition cannot be compiled as a module.
This is an old filesystem (= method to organize files on a harddisk
partition or a floppy disk) and not in use anymore. This option
would enlarge your kernel by about 28 kB. Let's all kill this beast:
say N. If you want to compile this as a module ( = code which can
be inserted in and removed from the running kernel whenever you
want), say M here and read Documentation/modules.txt. Note that the
filesystem of your root partition cannot be compiled as a module.
msdos fs support
CONFIG_MSDOS_FS
......@@ -1847,31 +1880,29 @@ CONFIG_PROC_FS
them. Also, you cannot read the files with less or more: you need to
use cat. The filesystem is explained in the Kernel Hacker's Guide,
available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/LDP. This option will enlarge your
kernel by about 18 kB. It's totally cool; for example, "cat
/proc/interrupts" gives information about what the different IRQs
are used for at the moment (there is a small number of Interrupt
ReQuest lines in your computer that are used by the periphery to
gain the CPU's attention - often a source of trouble if two devices
are mistakenly configured to use the same IRQ). Several programs
depend on this, so everyone should say Y here.
sunsite.unc.edu:/pub/Linux/docs/LDP and also on the proc(8) manpage
("man 8 proc"). This option will enlarge your kernel by about 18
kB. It's totally cool; for example, "cat /proc/interrupts" gives
information about what the different IRQs are used for at the moment
(there is a small number of Interrupt ReQuest lines in your computer
that are used by the periphery to gain the CPU's attention - often a
source of trouble if two devices are mistakenly configured to use
the same IRQ). Several programs depend on this, so everyone should
say Y here.
NFS filesystem support
CONFIG_NFS_FS
If you are connected to a network (using SLIP, PPP or ethernet, not
term [term is a program which gives you almost full Internet
connectivity if you have a regular dial up shell account on some
Internet connected Unix computer. Read the Term-HOWTO, available via
ftp (user: anonymous) on sunsite.unc.edu:/pub/Linux/docs/HOWTO]) and
want to mount files residing on another UNIX computer (the NFS
server) using the NetworkFileSharing protocol, say Y. "Mounting
files" means that the client can access the files with usual UNIX
commands as if they were sitting on the client's harddisk. For this
to work, the server must run the programs nfsd and mountd (but does
not need to have NFS filesystem support enabled). NFS is explained
in the Network Administrator's Guide, available via ftp (user:
anonymous) in sunsite.unc.edu:/pub/Linux/docs/LDP, and on its man
page: "man nfs". There is also a NFS-FAQ in
If you are connected to some other (usually local) Unix computer
(using SLIP, PLIP, PPP or ethernet) and want to mount files
residing on that computer (the NFS server) using the Network
File Sharing protocol, say Y. "Mounting files" means that the client
can access the files with usual UNIX commands as if they were
sitting on the client's harddisk. For this to work, the server must
run the programs nfsd and mountd (but does not need to have NFS
filesystem support enabled). NFS is explained in the Network
Administrator's Guide, available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/LDP, and on its man page: "man
nfs". There is also a NFS-FAQ in
sunsite.unc.edu:/pub/Linux/docs/faqs which presumes that you know
the basics of NFS already. If you say Y here, you should have said Y
to TCP/IP networking also. This option would enlarge your kernel by
......@@ -1881,6 +1912,18 @@ CONFIG_NFS_FS
here and read Documentation/modules.txt. If you don't know what all
this is about, say N.
Root file system on NFS
CONFIG_ROOT_NFS
If you want your Linux box to mount its whole root filesystem from
some other computer over the net via NFS (presumably because your
box doesn't have a harddisk), say Y here. You will then have to
specify the directory that should be remotely mounted with the
"root" kernel command line option. See the documentation of your
boot loader (lilo or loadlin) about how to pass options to the
kernel. The lilo procedure is also explained in the SCSI-HOWTO,
available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/HOWTO.) Most people say N here.
ISO9660 cdrom filesystem support
CONFIG_ISO9660_FS
If you have a CDROM and want to do more with it than just listen to
......@@ -1909,25 +1952,27 @@ System V and Coherent filesystem support
CONFIG_SYSV_FS
SCO, Xenix and Coherent are commercial Unix systems for intel
machines. Enabling this option would allow you to read and write to
and from their floppies and harddisk partitions. You need this if
you want to run iBCS2 (iBCS2 [Intel Binary Compatibility Standard]
is a kernel module which lets you run SCO, Xenix, Wyse, Unix Ware,
Dell Unix and System V programs under Linux and is often needed to
run commercial software, most prominently WordPerfect. It's in
tsx-11.mit.edu:/pub/linux/BETA). If you only intend to mount files
from some other Unix over the network using NFS, you don't need this
(but you need nfs filesystem support obviously). Note that this
option is generally not needed for floppies, since a good portable
way to transport files between unixes (and even to other operating
systems) is given by the tar program ("man tar"). Note also that
this option has nothing to do whatsoever with the option "System V
IPC". Read about the System V filesystem in
Documentation/filesystems/sysv-fs.txt. This option will enlarge your
kernel by about 34 kB. If you want to compile this as a module
( = code which can be inserted in and removed from the running
kernel whenever you want), say M here and read
and from their floppies and harddisk partitions. If you have a
floppy or harddisk partition like that, it is probable that they
contain binaries from those other Unix systems; in order to run
these binaries, you will want to install iBCS2 (iBCS2 [Intel Binary
Compatibility Standard] is a kernel module which lets you run SCO,
Xenix, Wyse, Unix Ware, Dell Unix and System V programs under Linux
and is often needed to run commercial software, most prominently
WordPerfect. It's in tsx-11.mit.edu:/pub/linux/BETA). If you only
intend to mount files from some other Unix over the network using
NFS, you don't need this (but you need nfs filesystem support
obviously). Note that this option is generally not needed for
floppies, since a good portable way to transport files between
unixes (and even to other operating systems) is given by the tar
program ("man tar"). Note also that this option has nothing to do
whatsoever with the option "System V IPC". Read about the System V
filesystem in Documentation/filesystems/sysv-fs.txt. This option
will enlarge your kernel by about 34 kB. If you want to compile this
as a module ( = code which can be inserted in and removed from the
running kernel whenever you want), say M here and read
Documentation/modules.txt. If you haven't heard about all of this
before, it's safe to say N.
before, it's safe to say N.
SMB filesystem (to mount WfW shares etc..) support
CONFIG_SMB_FS
......@@ -1947,14 +1992,17 @@ CONFIG_SMB_FS
the programs lynx, netscape or Mosaic). If you want to compile this
as a module ( = code which can be inserted in and removed from the
running kernel whenever you want), say M here and read
Documentation/modules.txt. Most people say N here.
Documentation/modules.txt. Most people say N, however.
Cyclades async mux support
CONFIG_CYCLADES
This is a card which gives you many serial ports. You would need
something like this to connect more than two modems to your linux
box, for instance in order to become a BBS. If you haven't heard
about it, it's safe to say N.
box, for instance in order to become a BBS. If you want to compile
this as a module ( = code which can be inserted in and removed from
the running kernel whenever you want), say M here and read
Documentation/modules.txt. If you haven't heard about it, it's safe
to say N.
Stallion multiport serial support
CONFIG_STALDRV
......@@ -1989,9 +2037,10 @@ CONFIG_PRINTER
running kernel whenever you want), say M here and read
Documentation/modules.txt. If you intend to use PLIP (Parallel Line
Internet Protocol is mainly used to create a mini network by
connecting the parallel ports of two local machines) and a parallel
printer, you should compile both as modules because the drivers
don't like each other.
connecting the parallel ports of two local machines) or a ethernet
network pocket adaptor attaching to the parallel port and a parallel
printer as well, you should compile both drivers as modules because
the drivers don't like each other.
Logitech busmouse support
CONFIG_BUSMOUSE
......@@ -2163,12 +2212,12 @@ CONFIG_PROFILE_SHIFT
# LocalWords: cdrom harddisk diskless netboot nfs xzvf ATAPI MB harddrives ide
# LocalWords: HD harddisks CDROMs IDECD NEC MITSUMI filesystem XT XD PCI bios
# LocalWords: ISA EISA Microchannel VESA BIOSes bussystem IPC SYSVIPC ipc Ctrl
# LocalWords: InterProcessCommunication BINFMT Linkable http ac uk jo html GCC
# LocalWords: BINFMT Linkable http ac uk jo html GCC Sparc AVANTI CABRIOLET EB
# LocalWords: netscape gcc LD CC toplevel MODVERSIONS insmod rmmod modprobe IP
# LocalWords: genksyms INET loopback gatewaying ethernet internet PPP ARP Arp
# LocalWords: howto multicasting MULTICAST MBONE firewalling ipfw ACCT resp ip
# LocalWords: proc acct IPIP encapsulator decapsulator klogd PCTCP RARP EXT PS
# LocalWords: telneting AddressResolutionProtocol subnetted NAGLE rlogin NOSR
# LocalWords: telneting subnetted NAGLE rlogin NOSR ttyS TGA techinfo mbone nl
# LocalWords: Mb SKB IPX Novell Netware dosemu Appletalk DDP ATALK tapedrive
# LocalWords: SD CHR scsi thingy SG CD LUNs LUN jukebox Adaptec BusLogic EATA
# LocalWords: buslogic DMA DPT ATT eata dma PIO UltraStor fdomain umsdos ext
......@@ -2196,5 +2245,7 @@ CONFIG_PROFILE_SHIFT
# LocalWords: Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard
# LocalWords: Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem
# LocalWords: carleton Deskstation DECstation SUNFD JENSEN Noname XXXM SLiRP
# LocalWords: pppd Zilog ZS soundcards SRM bootloader SMP smp ez mainmenu rarp
# LocalWords: RTNETLINK mknod
# LocalWords: pppd Zilog ZS soundcards SRM bootloader ez mainmenu rarp ipfwadm
# LocalWords: RTNETLINK mknod xos MTU lwared Macs mac netatalk macs cs Wolff
# LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress
# LocalWords: ICL EtherTeam ETH IDESCSI TXC
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 46
SUBLEVEL = 47
ARCH = i386
......
......@@ -19,9 +19,9 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_BINFMT_ELF" = "y" ]; then
bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF
fi
#bool 'Use -mpentium flag for Pentium-specific optimizations' CONFIG_M586
#bool 'Use Pentium-specific optimizations (does NOT work on i386)' CONFIG_M586
#if [ "$CONFIG_M586" = "n" ]; then
bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486
bool 'Use 486-specific optimizations (does NOT work on i386)' CONFIG_M486
#fi
mainmenu_option next_comment
......
......@@ -41,6 +41,7 @@ CONFIG_BLK_DEV_IDECD=y
# Networking options
#
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
CONFIG_INET=y
# CONFIG_IP_FORWARD is not set
# CONFIG_IP_MULTICAST is not set
......@@ -122,10 +123,6 @@ CONFIG_ISO9660_FS=y
# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_APM is not set
# CONFIG_APM_IGNORE_USER_SUSPEND is not set
# CONFIG_APM_DO_ENABLE is not set
CONFIG_APM_CPU_IDLE=y
# CONFIG_APM_DISPLAY_BLANK is not set
#
# Sound
......
......@@ -19,7 +19,6 @@ M_OBJS :=
L_OBJS := tty_io.o n_tty.o console.o keyboard.o serial.o \
tty_ioctl.o pty.o vt.o mem.o vc_screen.o random.o \
defkeymap.o consolemap.o selection.o
SYMTAB_OBJS :=
ifeq ($(CONFIG_CYCLADES),y)
L_OBJS += cyclades.o
......@@ -98,8 +97,7 @@ L_OBJS += tpqic02.o
endif
ifdef CONFIG_APM
L_OBJS += apm_bios.o
SYMTAB_OBJS += apm_bios.o
LX_OBJS += apm_bios.o
endif
ifdef M
......
......@@ -41,6 +41,9 @@
*
* New TIOCLINUX variants added.
* -- mj@k332.feld.cvut.cz, 19-Nov-95
*
* Restrict vt switching via ioctl()
* -- grif@cs.ucr.edu, 5-Dec-95
*/
#include <linux/config.h>
......@@ -97,6 +100,7 @@ int last_console = 0;
int kmsg_redirect = 0;
struct tty_struct * redirect = NULL;
struct wait_queue * keypress_wait = NULL;
char vt_dont_switch = 0;
static void initialize_tty_struct(struct tty_struct *tty);
......@@ -523,7 +527,7 @@ void complete_change_console(unsigned int new_console)
{
unsigned char old_vc_mode;
if (new_console == fg_console)
if ((new_console == fg_console) || (vt_dont_switch))
return;
if (!vc_cons_allocated(new_console))
return;
......@@ -594,7 +598,7 @@ void complete_change_console(unsigned int new_console)
*/
void change_console(unsigned int new_console)
{
if (new_console == fg_console)
if ((new_console == fg_console) || (vt_dont_switch))
return;
if (!vc_cons_allocated(new_console))
return;
......
......@@ -5,6 +5,7 @@
*
* Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
* Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
* Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
*/
#include <linux/types.h>
......@@ -28,6 +29,7 @@
#include "diacr.h"
#include "selection.h"
extern char vt_dont_switch;
extern struct tty_driver console_driver;
#define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
......@@ -1094,7 +1096,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return i;
return con_get_unimap(ct, &(ud->entry_ct), list);
}
case VT_LOCKSWITCH:
if (!suser())
return -EPERM;
vt_dont_switch = 1;
return 0;
case VT_UNLOCKSWITCH:
if (!suser())
return -EPERM;
vt_dont_switch = 0;
return 0;
default:
return -ENOIOCTLCMD;
}
......
......@@ -477,7 +477,12 @@ el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);
if (dev->mem_start) { /* Use the shared memory. */
#ifdef notdef
/* Officially this is what we are doing, but the readl() is faster */
memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
#else
((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
return;
}
......
......@@ -32,8 +32,6 @@ static const char *version =
Much of this code should have been cleaned up, but every attempt
has broken some clone part.
Doesn't currently work on all shared memory cards.
Sources:
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
*/
......@@ -512,8 +510,9 @@ static void ei_receive(struct device *dev)
if (rx_pkt_count > high_water_mark)
high_water_mark = rx_pkt_count;
/* Bug alert! Reset ENISR_OVER to avoid spurious overruns! */
outb_p(ENISR_RX+ENISR_RX_ERR+ENISR_OVER, e8390_base+EN0_ISR);
/* We used to also ack ENISR_OVER here, but that would sometimes mask
a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
return;
}
......@@ -550,7 +549,7 @@ static void ei_rx_overrun(struct device *dev)
/* Remove packets right away. */
ei_receive(dev);
outb_p(0xff, e8390_base+EN0_ISR);
outb_p(ENISR_OVER, e8390_base+EN0_ISR);
/* Generic 8390 insns to start up again, same as in open_8390(). */
outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
......
......@@ -17,6 +17,19 @@
**********************
v2.22 (95/12/08)
- IRQ is always printed as a decimal, instead of a hex number.
- Replaced most remaining printk's with BUGMSG macros.
- Moved variables for VERIFY_ACK from the Outgoing struct into
the lp struct; Outgoing is really for packet-splitting info
only.
- Simplified INTMASK handling using a memory variable to keep a
"running total."
- Tracked down more (maybe the last?) "missed IRQ" messages caused
by TX-done IRQ's occurring WHILE arcnet??_send_packet was in
progress. These were pretty obscure and mostly harmless.
- Made an actual non-ALPHA release of the thing.
v2.21 ALPHA (95/11/29)
- "Unknown protocol ID" messages now also indicate the station
which sent the unrecognized packet, to aid in debugging network
......@@ -146,12 +159,15 @@
mainly a portability fix. This will confuse autoprobe a bit, so
test that too.
- What about cards with shared memory that can be "turned off?"
- NFS mount freezes after several megabytes to SOSS for DOS.
unmount/remount fixes it. Is this arcnet-specific? I don't know.
(or that have none at all, like the SMC PC500longboard)
- Some newer ARCnets support promiscuous mode, supposedly. If
someone sends me information, I'll try to implement it.
- Dump Linux 1.2 support and its ugly #ifdefs.
- Add support for the new 1.3.x IP header cache features.
- Support printk's priority levels.
- Make arcnetE_send_packet use arcnet_prepare_tx for loading the
packet into ARCnet memory.
- Move the SKB and memory dump code into separate functions.
- ATA protocol support??
- Banyan VINES TCP/IP support??
......@@ -162,17 +178,17 @@
Donald Becker - it didn't work :)
- skeleton.c v0.05 dated 11/16/93 by Donald Becker
(from Linux Kernel 1.1.45)
- RFC's 1201 and 1051 - re: TCP/IP over ARCnet
- The official ARCnet data sheets (!) thanks to Ken Cornetet
<kcornete@nyx10.cs.du.edu>
- RFC's 1201 and 1051 - re: TCP/IP over ARCnet
- net/inet/eth.c (from kernel 1.1.50) for header-building info...
- net/inet/eth.c (from kernel 1.1.50) for header-building info.
- Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
- Textual information and more alternate source from Joachim Koenig
<jojo@repas.de>
*/
static const char *version =
"arcnet.c: v2.21 ALPHA 95/11/29 Avery Pennarun <apenwarr@foxnet.net>\n";
"arcnet.c: v2.22 95/12/08 Avery Pennarun <apenwarr@foxnet.net>\n";
......@@ -368,6 +384,8 @@ extern struct device *irq2dev_map[16];
#define COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */
#define RESET (ioaddr+8) /* software reset writable */
#define SETMASK outb(lp->intmask,INTMASK);
/* Time needed for various things (in clock ticks, 1/100 sec) */
/* We mostly don't bother with these - watch out. */
#define RESETtime 40 /* reset */
......@@ -396,12 +414,6 @@ extern struct device *irq2dev_map[16];
#define RES2flag 0x40 /* unused */
#define NORXflag 0x80 /* receiver inhibited */
#ifdef DETECT_RECONFIGS
#define RECON_flag RECONflag
#else
#define RECON_flag 0
#endif
/* in the command register, the following bits have these meanings:
* 0-2 command
* 3-4 page number (for enable rcv/xmt command)
......@@ -530,26 +542,26 @@ struct Outgoing
segnum, /* segment being sent */
numsegs, /* number of segments */
seglen; /* length of segment */
#ifdef VERIFY_ACK
short lastload_dest, /* can last loaded packet be acked? */
lasttrans_dest; /* can last TX'd packet be acked? */
#endif
};
/* Information that needs to be kept for each board. */
struct arcnet_local {
struct enet_statistics stats;
u_char arcnum; /* arcnet number - our 8-bit address */
u_short sequence; /* sequence number (incs with each packet) */
u_char recbuf, /* receive buffer # (0 or 1) */
txbuf, /* transmit buffer # (2 or 3) */
txready; /* buffer where a packet is ready to send */
u_char stationid, /* our 8-bit station address */
recbuf, /* receive buffer # (0 or 1) */
txbuf, /* transmit buffer # (2 or 3) */
txready, /* buffer where a packet is ready to send */
intmask; /* current value of INTMASK register */
short intx, /* in TX routine? */
in_txhandler, /* in TX_IRQ handler? */
sending; /* transmit in progress? */
short tx_left; /* segments of split packet left to TX */
#ifdef VERIFY_ACK
short lastload_dest, /* can last loaded packet be acked? */
lasttrans_dest; /* can last TX'd packet be acked? */
#endif
#if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD)
time_t first_recon, /* time of "first" RECON message to count */
......@@ -685,7 +697,7 @@ arcnet_probe(struct device *dev)
printk(version);
#if 1
#if 0
BUGLVL(D_NORMAL)
{
printk("arcnet: ***\n");
......@@ -696,7 +708,7 @@ arcnet_probe(struct device *dev)
printk("arcnet: ***\n");
}
#else
BUGLVL(D_INIT)
BUGLVL(D_EXTRA)
{
printk("arcnet: ***\n");
printk("arcnet: * Read README.arcnet for important release notes!\n");
......@@ -707,7 +719,7 @@ arcnet_probe(struct device *dev)
}
#endif
BUGMSG(D_INIT,"given: base %lXh, IRQ %Xh, shmem %lXh\n",
BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n",
dev->base_addr,dev->irq,dev->mem_start);
#ifndef MODULE
......@@ -758,11 +770,9 @@ arcnet_probe(struct device *dev)
if (!dev->base_addr || !dev->irq || !dev->mem_start
|| !dev->rmem_start)
{
printk("%6s: loadable modules can't autoprobe!\n",dev->name);
printk("%6s: try using io=, irqnum=, and shmem= on the insmod line.\n",
dev->name);
printk("%6s: you may also need num= to change the device name. (ie. num=1 for arc1)\n",
dev->name);
BUGMSG(D_NORMAL,"loadable modules can't autoprobe!\n");
BUGMSG(D_NORMAL,"try using io=, irqnum=, and shmem= on the insmod line.\n");
BUGMSG(D_NORMAL,"you may also need num= to change the device name. (ie. num=1 for arc1)\n");
return ENODEV;
}
#endif
......@@ -771,8 +781,8 @@ arcnet_probe(struct device *dev)
int irqval = request_irq(dev->irq, &arcnet_interrupt, 0,
"arcnet");
if (irqval) {
printk("%6s: unable to get IRQ %d (irqval=%d).\n",
dev->name,dev->irq, irqval);
BUGMSG(D_NORMAL,"unable to get IRQ %d (irqval=%d).\n",
dev->irq, irqval);
return EAGAIN;
}
......@@ -782,8 +792,8 @@ arcnet_probe(struct device *dev)
/* Grab the region so we can find another board if autoIRQ fails. */
request_region(dev->base_addr, ARCNET_TOTAL_SIZE,"arcnet");
printk("%6s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.\n",
dev->name, dev->base_addr, dev->irq, dev->mem_start);
BUGMSG(D_NORMAL,"ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.\n",
dev->base_addr, dev->irq, dev->mem_start);
/* Initialize the device structure. */
dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
......@@ -819,14 +829,12 @@ arcnet_probe(struct device *dev)
arcnet_reset(dev);
JIFFER(50);
BUGMSG(D_NORMAL,"We appear to be station %d (%02Xh)\n",
lp->arcnum,lp->arcnum);
if (lp->arcnum==0)
printk("%6s: WARNING! Station address 0 is reserved for broadcasts!\n",
dev->name);
if (lp->arcnum==255)
printk("%6s: WARNING! Station address 255 may confuse DOS networking programs!\n",
dev->name);
dev->dev_addr[0]=lp->arcnum;
lp->stationid,lp->stationid);
if (lp->stationid==0)
BUGMSG(D_NORMAL,"WARNING! Station address 0 is reserved for broadcasts!\n");
if (lp->stationid==255)
BUGMSG(D_NORMAL,"WARNING! Station address 255 may confuse DOS networking programs!\n");
dev->dev_addr[0]=lp->stationid;
lp->sequence=1;
lp->recbuf=0;
......@@ -907,9 +915,6 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
/* if we do this, we're sure to get an IRQ since the card has
* just reset and the NORXflag is on until we tell it to start
* receiving.
*
* However, this could, theoretically, cause a lockup. Maybe I'm just
* not very good at theory! :)
*/
outb(NORXflag,INTMASK);
JIFFER(RESETtime);
......@@ -919,8 +924,8 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
airq = autoirq_report(0);
BUGLVL(D_INIT) if (airq)
printk("%6s: autoirq is %d\n", dev->name, airq);
if (airq)
BUGMSG(D_INIT," autoirq is %d\n", airq);
/* if there was no autoirq AND the user hasn't set any defaults,
* give up.
......@@ -1014,7 +1019,8 @@ int arcnet_reset(struct device *dev)
int delayval,recbuf=lp->recbuf;
u_char *cardmem;
outb(0,INTMASK); /* no IRQ's, please! */
lp->intmask=0;
SETMASK; /* no IRQ's, please! */
BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
dev->name,inb(STATUS));
......@@ -1034,7 +1040,7 @@ int arcnet_reset(struct device *dev)
BUGMSG(D_INIT,"reset failed: TESTvalue not present.\n");
return 1;
}
lp->arcnum=cardmem[1]; /* save address for later use */
lp->stationid=cardmem[1]; /* save address for later use */
/* clear out status variables */
recbuf=lp->recbuf=0;
......@@ -1051,7 +1057,11 @@ int arcnet_reset(struct device *dev)
EnableReceiver();
/* re-enable interrupts */
outb(NORXflag|RECON_flag,INTMASK);
lp->intmask|=NORXflag;
#ifdef DETECT_RECONFIGS
lp->intmask|=RECONflag;
#endif
SETMASK;
/* done! return success. */
return 0;
......@@ -1094,7 +1104,7 @@ static int arcnetE_init(struct device *dev)
ether_setup(dev); /* we're emulating ether here, not ARCnet */
dev->dev_addr[0]=0;
dev->dev_addr[5]=lp->arcnum;
dev->dev_addr[5]=lp->stationid;
dev->mtu=512-sizeof(struct HardHeader)-dev->hard_header_len-1;
dev->open=NULL;
dev->stop=NULL;
......@@ -1114,7 +1124,7 @@ static int arcnetS_init(struct device *dev)
arcnet_setup(dev);
/* And now fill particular fields with arcnet values */
dev->dev_addr[0]=lp->arcnum;
dev->dev_addr[0]=lp->stationid;
dev->hard_header_len=sizeof(struct S_ClientData);
dev->mtu=512-sizeof(struct HardHeader)-dev->hard_header_len
+ S_EXTRA_CLIENTDATA;
......@@ -1204,11 +1214,11 @@ arcnet_open(struct device *dev)
/* make sure we're ready to receive IRQ's.
* arcnet_reset sets this for us, but if we receive one before
* START is set to 1, bad things happen.
* START is set to 1, it could be ignored.
*/
outb(0,INTMASK);
JIFFER(ACKtime);
outb(NORXflag|RECON_flag,INTMASK);
SETMASK;
MOD_INC_USE_COUNT;
return 0;
......@@ -1227,7 +1237,8 @@ arcnet_close(struct device *dev)
START=0;
/* Flush TX and disable RX */
outb(0,INTMASK); /* no IRQ's (except RESET, of course) */
lp->intmask=0;
SETMASK; /* no IRQ's (except RESET, of course) */
outb(NOTXcmd,COMMAND); /* stop transmit */
outb(NORXcmd,COMMAND); /* disable receive */
......@@ -1309,20 +1320,21 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
return 1;
}
outb(0,INTMASK);
lp->intmask &= ~TXFREEflag;
SETMASK;
if (status&TXFREEflag) /* transmit _DID_ finish */
{
BUGMSG(D_EXTRA,"tx timed out - missed IRQ? (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
status,lp->intx,
lp->in_txhandler,tickssofar);
BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, inTXh=%d, ticks=%d, mask=%Xh)\n",
status,lp->in_txhandler,tickssofar,
lp->intmask);
lp->stats.tx_errors++;
}
else
{
BUGMSG(D_NORMAL,"tx timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
status,lp->intx,
lp->in_txhandler,tickssofar);
BUGMSG(D_NORMAL,"tx timed out (status=%Xh, inTXh=%d, tickssofar=%d, intmask=%Xh)\n",
status,lp->in_txhandler,tickssofar,
lp->intmask);
lp->stats.tx_errors++;
lp->stats.tx_aborted_errors++;
......@@ -1340,8 +1352,6 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
lp->txready=0;
lp->sending=0;
outb(NORXflag|RECON_flag,INTMASK);
return 1;
}
......@@ -1349,8 +1359,8 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
we are passed NULL. Caution: dev_tint() handles the cli()/sti()
itself. */
if (skb == NULL) {
printk("%6s: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n",
dev->name,inb(STATUS),lp->intx,jiffies-dev->trans_start);
BUGMSG(D_NORMAL,"tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n",
inb(STATUS),lp->intx,jiffies-dev->trans_start);
lp->stats.tx_errors++;
dev_tint(dev);
return 0;
......@@ -1358,9 +1368,10 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
if (lp->txready) /* transmit already in progress! */
{
printk("%6s: trying to start new packet while busy! (status=%Xh)\n",
dev->name,inb(STATUS));
outb(0,INTMASK);
BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
inb(STATUS));
lp->intmask &= ~TXFREEflag;
SETMASK;
outb(NOTXcmd,COMMAND); /* abort current send */
arcnet_inthandler(dev); /* fake an interrupt */
lp->stats.tx_errors++;
......@@ -1374,8 +1385,8 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
if (set_bit(0, (void*)&dev->tbusy) != 0)
{
printk("%6s: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
dev->name,inb(STATUS),lp->intx,jiffies-dev->trans_start);
BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
inb(STATUS),lp->intx,jiffies-dev->trans_start);
lp->stats.tx_errors++;
lp->stats.tx_fifo_errors++;
return -EBUSY;
......@@ -1394,9 +1405,6 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
int ioaddr=dev->base_addr,bad;
struct Outgoing *out=&(lp->outgoing);
BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
inb(STATUS),lp->intx);
lp->intx++;
bad=arcnet_send_packet_bad(skb,dev);
......@@ -1407,7 +1415,7 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
}
TBUSY=1;
out->length = 1 < skb->len ? skb->len : 1;
out->hdr=(struct ClientData*)skb->data;
out->skb=skb;
......@@ -1415,9 +1423,9 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
BUGLVL(D_SKB)
{
short i;
for( i=0; i< skb->len; i++)
for(i=0; i<skb->len; i++)
{
if( i%16 == 0 ) printk("\n[%04hX] ",i);
if(i%16 == 0) printk("\n[%04hX] ",i);
printk("%02hX ",((unsigned char*)skb->data)[i]);
}
printk("\n");
......@@ -1425,16 +1433,14 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
out->hdr->sequence=(lp->sequence++);
/*arcnet_go_tx(dev);*/ /* Make sure buffers are clear */
/* fits in one packet? */
if (out->length-EXTRA_CLIENTDATA<=XMTU)
{
BUGMSG(D_DURING,"not splitting %d-byte packet. (split_flag=%d)\n",
out->length,out->hdr->split_flag);
BUGLVL(D_EXTRA) if (out->hdr->split_flag)
printk("%6s: short packet has split_flag set?! (split_flag=%d)\n",
dev->name,out->hdr->split_flag);
if (out->hdr->split_flag)
BUGMSG(D_NORMAL,"short packet has split_flag set?! (split_flag=%d)\n",
out->hdr->split_flag);
out->numsegs=1;
out->segnum=1;
arcnetAS_prepare_tx(dev,
......@@ -1463,9 +1469,8 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
+ sizeof(struct ClientData);
out->dataleft=out->length-sizeof(struct ClientData);
out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
out->segnum=0;
BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
out->length,out->numsegs);
......@@ -1500,6 +1505,11 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
dev->trans_start=jiffies;
lp->intx--;
/* make sure we didn't ignore a TX IRQ while we were in here */
lp->intmask |= TXFREEflag;
SETMASK;
return 0;
}
......@@ -1510,14 +1520,12 @@ static int
arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
int bad;
int ioaddr=dev->base_addr,bad;
union ArcPacket *arcpacket =
(union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
u_char *arcsoft,daddr;
short offset,length=skb->len+1;
BUGMSG(D_DURING,"in arcnetE_send_packet (skb=%p)\n",skb);
lp->intx++;
bad=arcnet_send_packet_bad(skb,dev);
......@@ -1531,11 +1539,12 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
if (length>XMTU)
{
printk("%6s: MTU must be <= 493 for ethernet encap (length=%d).\n",
dev->name,length);
printk("%6s: transmit aborted.\n",dev->name);
BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
length);
BUGMSG(D_NORMAL,"transmit aborted.\n");
dev_kfree_skb(skb,FREE_WRITE);
lp->intx--;
return 0;
}
......@@ -1603,7 +1612,7 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
}
#ifdef VERIFY_ACK
lp->outgoing.lastload_dest=daddr;
lp->lastload_dest=daddr;
#endif
lp->txready=lp->txbuf; /* packet is ready for sending */
......@@ -1618,6 +1627,11 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
dev->trans_start=jiffies;
lp->intx--;
/* make sure we didn't ignore a TX IRQ while we were in here */
lp->intmask |= TXFREEflag;
SETMASK;
return 0;
}
......@@ -1633,9 +1647,6 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
lp->intx++;
BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
inb(STATUS),lp->intx);
bad=arcnet_send_packet_bad(skb,dev);
if (bad)
{
......@@ -1652,15 +1663,12 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
short i;
for(i=0; i<skb->len; i++)
{
if( i%16 == 0 ) printk("\n[%04hX] ",i);
if (i%16 == 0) printk("\n[%04hX] ",i);
printk("%02hX ",((unsigned char*)skb->data)[i]);
}
printk("\n");
}
/*if (lp->txready && inb(STATUS)&TXFREEflag)
arcnet_go_tx(dev);*/
/* fits in one packet? */
if (length-S_EXTRA_CLIENTDATA<=XMTU)
{
......@@ -1683,7 +1691,7 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
}
else /* too big for one - not accepted */
{
printk("arcnetS: packet too long (length=%d)\n",
BUGMSG(D_NORMAL,"packet too long (length=%d)\n",
length);
dev_kfree_skb(skb,FREE_WRITE);
lp->stats.tx_dropped++;
......@@ -1693,6 +1701,11 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
dev->trans_start=jiffies;
lp->intx--;
/* make sure we didn't ignore a TX IRQ while we were in here */
lp->intmask |= TXFREEflag;
SETMASK;
return 0;
}
......@@ -1704,20 +1717,22 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
static void arcnetA_continue_tx(struct device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
int maxsegsize=XMTU-4;
int ioaddr=dev->base_addr,maxsegsize=XMTU-4;
struct Outgoing *out=&(lp->outgoing);
BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
inb(STATUS),lp->intx,lp->in_txhandler,lp->intmask);
if (lp->txready)
{
printk("%6s: continue_tx: called with packet in buffer!\n",
dev->name);
BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
return;
}
if (out->segnum>=out->numsegs)
{
printk("%6s: continue_tx: building segment %d of %d!\n",
dev->name,out->segnum+1,out->numsegs);
BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n",
out->segnum+1,out->numsegs);
}
if (!out->segnum) /* first packet */
......@@ -1840,13 +1855,20 @@ arcnetAS_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
}
#ifdef VERIFY_ACK
lp->outgoing.lastload_dest=daddr;
lp->lastload_dest=daddr;
#endif
lp->txready=lp->txbuf; /* packet is ready for sending */
}
/* Actually start transmitting a packet that was placed in the card's
* buffer by arcnetAS_prepare_tx. Returns 1 if a Tx is really started.
*
* This should probably always be called with the INTMASK register set to 0,
* so go_tx is not called recursively.
*
* The enable_irq flag determines whether to actually write INTMASK value
* to the card; TXFREEflag is always OR'ed into the memory variable either
* way.
*/
static int
arcnet_go_tx(struct device *dev,int enable_irq)
......@@ -1854,19 +1876,15 @@ arcnet_go_tx(struct device *dev,int enable_irq)
struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
int ioaddr=dev->base_addr;
BUGMSG(D_DURING,"go_tx: status=%Xh\n",
inb(STATUS));
outb(0,INTMASK);
BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
inb(STATUS),lp->intmask,lp->txready,lp->sending);
if (lp->sending || !lp->txready)
{
if (enable_irq)
if (enable_irq && lp->sending)
{
if (lp->sending)
outb(TXFREEflag|NORXflag|RECON_flag,INTMASK);
else
outb(NORXflag|RECON_flag,INTMASK);
lp->intmask |= TXFREEflag;
SETMASK;
}
return 0;
}
......@@ -1879,12 +1897,13 @@ arcnet_go_tx(struct device *dev,int enable_irq)
lp->sending++;
#ifdef VERIFY_ACK
lp->outgoing.lasttrans_dest=lp->outgoing.lastload_dest;
lp->outgoing.lastload_dest=0;
lp->lasttrans_dest=lp->lastload_dest;
lp->lastload_dest=0;
#endif
if (enable_irq)
outb(TXFREEflag|NORXflag|RECON_flag,INTMASK);
lp->intmask |= TXFREEflag;
if (enable_irq) SETMASK;
return 1;
}
......@@ -1933,38 +1952,21 @@ arcnet_inthandler(struct device *dev)
if (IF_INTERRUPT)
{
printk("%6s: DRIVER PROBLEM! Nested arcnet interrupts!\n",
dev->name);
BUGMSG(D_NORMAL,"DRIVER PROBLEM! Nested arcnet interrupts!\n");
return; /* don't even try. */
}
outb(0,INTMASK);
INTERRUPT = 1;
BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh)\n",inb(STATUS));
BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
inb(STATUS),lp->intmask);
#if 1 /* Whatever you do, don't set this to 0. */
do
{
status = inb(STATUS);
didsomething=0;
#if 0 /* no longer necessary - doing checking in arcnet_interrupt now */
if (!dev->start)
{
BUGMSG(D_DURING,"ARCnet not yet initialized. irq ignored. (status=%Xh)\n",
status);
if (!(status&NORXflag))
outb(NORXflag|RECON_flag,INTMASK);
/* using dev->interrupt here instead of INTERRUPT
* because if dev->start is 0, the other devices
* probably do not exist.
*/
dev->interrupt=0;
return;
}
#endif
/* RESET flag was enabled - card is resetting and if RX
* is disabled, it's NOT because we just got a packet.
*/
......@@ -1975,7 +1977,7 @@ arcnet_inthandler(struct device *dev)
status);
}
#ifdef DETECT_RECONFIGS
if (status & RECONflag)
if (status & (lp->intmask) & RECONflag)
{
outb(CFLAGScmd|CONFIGclear,COMMAND);
lp->stats.tx_carrier_errors++;
......@@ -1991,8 +1993,7 @@ arcnet_inthandler(struct device *dev)
jiffies-lp->last_recon > HZ*10)
{
if (lp->network_down)
printk("%6s: reconfiguration detected: cabling restored?\n",
dev->name);
BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
lp->first_recon=lp->last_recon=jiffies;
lp->num_recons=lp->network_down=0;
......@@ -2020,8 +2021,7 @@ arcnet_inthandler(struct device *dev)
&& lp->num_recons >= RECON_THRESHOLD)
{
lp->network_down=1;
printk("%6s: many reconfigurations detected: cabling problem?\n",
dev->name);
BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
}
else if (!lp->network_down
&& lp->last_recon-lp->first_recon > HZ*60)
......@@ -2039,7 +2039,7 @@ arcnet_inthandler(struct device *dev)
else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
{
if (lp->network_down)
printk("%6s: cabling restored?\n",dev->name);
BUGMSG(D_NORMAL,"cabling restored?\n");
lp->first_recon=lp->last_recon=0;
lp->num_recons=lp->network_down=0;
......@@ -2049,7 +2049,7 @@ arcnet_inthandler(struct device *dev)
#endif /* DETECT_RECONFIGS */
/* RX is inhibited - we must have received something. */
if (status & NORXflag)
if (status & lp->intmask & NORXflag)
{
int recbuf=lp->recbuf=!lp->recbuf;
......@@ -2065,24 +2065,27 @@ arcnet_inthandler(struct device *dev)
}
/* it can only be an xmit-done irq if we're xmitting :) */
if (status&TXFREEflag && !lp->in_txhandler && lp->sending)
/*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
if (status & lp->intmask & TXFREEflag)
{
struct Outgoing *out=&(lp->outgoing);
int was_sending=lp->sending;
lp->intmask &= ~TXFREEflag;
lp->in_txhandler++;
lp->sending--;
if (was_sending) lp->sending--;
BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
status,out->numsegs,out->segnum,out->skb);
#ifdef VERIFY_ACK
if (!(status&TXACKflag))
if (was_sending && !(status&TXACKflag))
{
if (lp->outgoing.lasttrans_dest != 0)
if (lp->lasttrans_dest != 0)
{
printk("%6s: transmit was not acknowledged! (status=%Xh, dest=%d)\n",
dev->name,status,
lp->outgoing.lasttrans_dest);
BUGMSG(D_NORMAL,"transmit was not acknowledged! (status=%Xh, dest=%d)\n",
status,lp->lasttrans_dest);
lp->stats.tx_errors++;
lp->stats.tx_carrier_errors++;
}
......@@ -2090,7 +2093,7 @@ arcnet_inthandler(struct device *dev)
{
BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%d)\n",
status,
lp->outgoing.lasttrans_dest);
lp->lasttrans_dest);
}
}
#endif
......@@ -2100,6 +2103,8 @@ arcnet_inthandler(struct device *dev)
if (lp->intx)
{
BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
inb(STATUS),lp->intx);
lp->in_txhandler--;
continue;
}
......@@ -2114,7 +2119,6 @@ arcnet_inthandler(struct device *dev)
TBUSY=0;
mark_bh(NET_BH);
}
lp->in_txhandler--;
continue;
}
......@@ -2145,7 +2149,7 @@ arcnet_inthandler(struct device *dev)
}
}
didsomething++;
lp->in_txhandler--;
}
else if (lp->txready && !lp->sending && !lp->intx)
......@@ -2160,17 +2164,7 @@ arcnet_inthandler(struct device *dev)
BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n\n",
inb(STATUS),boguscount);
if (dev->start && (lp->sending || (lp->txready && !lp->intx)))
outb(NORXflag|TXFREEflag|RECON_flag,INTMASK);
else
outb(NORXflag|RECON_flag,INTMASK);
#else /* Disable everything */
outb(RXcmd|(0<<3)|RXbcasts,COMMAND);
outb(NORXflag,INTMASK);
#endif
SETMASK; /* put back interrupt mask */
INTERRUPT=0;
}
......@@ -2206,8 +2200,8 @@ arcnet_rx(struct device *dev,int recbuf)
/* if source is 0, it's a "used" packet! */
if (saddr==0)
{
printk("%6s: discarding old packet. (status=%Xh)\n",
dev->name,inb(STATUS));
BUGMSG(D_NORMAL,"discarding old packet. (status=%Xh)\n",
inb(STATUS));
lp->stats.rx_errors++;
return;
}
......@@ -2249,8 +2243,8 @@ arcnet_rx(struct device *dev,int recbuf)
break;
case ARC_P_LANSOFT: /* don't understand. fall through. */
default:
printk("%6s: received unknown protocol %d (%Xh) from station %d.\n",
dev->name,arcsoft[0],arcsoft[0],saddr);
BUGMSG(D_NORMAL,"received unknown protocol %d (%Xh) from station %d.\n",
arcsoft[0],arcsoft[0],saddr);
lp->stats.rx_errors++;
lp->stats.rx_crc_errors++;
break;
......@@ -2324,7 +2318,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
if (in->skb) /* already assembling one! */
{
BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
BUGMSG(D_NORMAL,"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);
......@@ -2337,8 +2331,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
skb = alloc_skb(length, GFP_ATOMIC);
if (skb == NULL) {
printk("%6s: Memory squeeze, dropping packet.\n",
dev->name);
BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
lp->stats.rx_dropped++;
return;
}
......@@ -2383,8 +2376,8 @@ arcnetA_rx(struct device *dev,u_char *buf,
}
else
{
printk("%6s: funny-shaped ARP packet. (%Xh, %Xh)\n",
dev->name,arp->ar_hln,arp->ar_pln);
BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n",
arp->ar_hln,arp->ar_pln);
lp->stats.rx_errors++;
lp->stats.rx_crc_errors++;
}
......@@ -2393,7 +2386,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
BUGLVL(D_SKB)
{
short i;
for( i=0; i< skb->len; i++)
for(i=0; i< skb->len; i++)
{
if( i%16 == 0 ) printk("\n[%04hX] ",i);
printk("%02hX ",((unsigned char*)skb->data)[i]);
......@@ -2433,8 +2426,8 @@ arcnetA_rx(struct device *dev,u_char *buf,
if (in->skb && in->sequence!=arcsoft->sequence)
{
BUGMSG(D_EXTRA,"wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)\n",
in->sequence,arcsoft->sequence,
BUGMSG(D_NORMAL,"wrong seq number, aborting assembly (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
saddr,in->sequence,arcsoft->sequence,
arcsoft->split_flag);
kfree_skb(in->skb,FREE_WRITE);
in->skb=NULL;
......@@ -2449,7 +2442,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
arcsoft->split_flag);
if (in->skb) /* already assembling one! */
{
BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
BUGMSG(D_NORMAL,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
in->sequence,arcsoft->split_flag,
arcsoft->sequence);
lp->stats.rx_errors++;
......@@ -2463,7 +2456,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
if (in->numpackets>16)
{
BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
BUGMSG(D_NORMAL,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
arcsoft->split_flag);
lp->stats.rx_errors++;
lp->stats.rx_length_errors++;
......@@ -2474,8 +2467,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
+ sizeof(struct ClientData),
GFP_ATOMIC);
if (skb == NULL) {
printk("%6s: (split) memory squeeze, dropping packet.\n",
dev->name);
BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n");
lp->stats.rx_dropped++;
return;
}
......@@ -2504,7 +2496,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
*/
if (!in->skb)
{
BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
BUGMSG(D_NORMAL,"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++;
......@@ -2517,7 +2509,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
/* harmless duplicate? ignore. */
if (packetnum<=in->lastpacket-1)
{
BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
BUGMSG(D_NORMAL,"duplicate splitpacket ignored! (splitflag=%d)\n",
arcsoft->split_flag);
lp->stats.rx_errors++;
lp->stats.rx_frame_errors++;
......@@ -2525,7 +2517,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
}
/* "bad" duplicate, kill reassembly */
BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
BUGMSG(D_NORMAL,"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);
......@@ -2555,8 +2547,8 @@ arcnetA_rx(struct device *dev,u_char *buf,
{
if (!skb || !in->skb)
{
printk("%6s: ?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
dev->name,skb,in->skb);
BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
skb,in->skb);
}
else
{
......@@ -2565,7 +2557,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
BUGLVL(D_SKB)
{
short i;
short i;
for(i=0; i<skb->len; i++)
{
if( i%16 == 0 ) printk("\n[%04hX] ",i);
......@@ -2600,7 +2592,7 @@ arcnetE_rx(struct device *dev,u_char *arcsoft,
skb = alloc_skb(length, GFP_ATOMIC);
if (skb == NULL) {
printk("%6s: Memory squeeze, dropping packet.\n",dev->name);
BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
lp->stats.rx_dropped++;
return;
}
......@@ -2653,7 +2645,7 @@ arcnetS_rx(struct device *dev,u_char *buf,
skb = alloc_skb(length, GFP_ATOMIC);
if (skb == NULL) {
printk("arcnetS: Memory squeeze, dropping packet.\n");
BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
lp->stats.rx_dropped++;
return;
}
......@@ -2780,8 +2772,8 @@ int arcnetA_header(struct sk_buff *skb,struct device *dev,
head->protocol_id=ARC_P_ATALK;
break;
default:
printk("%6s: I don't understand protocol %d (%Xh)\n",
dev->name,type,type);
BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
type,type);
lp->stats.tx_errors++;
lp->stats.tx_aborted_errors++;
return 0;
......@@ -2850,7 +2842,7 @@ int arcnetS_header(struct sk_buff *skb,struct device *dev,
BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n");
break;
default:
printk("arcnetS: I don't understand protocol %d (%Xh)\n",
BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
type,type);
lp->stats.tx_errors++;
lp->stats.tx_aborted_errors++;
......@@ -2901,8 +2893,8 @@ int arcnetA_rebuild_header(void *buff,struct device *dev,unsigned long dst,
if(head->protocol_id != ARC_P_IP)
{
printk("%6s: I don't understand protocol type %d (%Xh) addresses!\n",
dev->name,head->protocol_id,head->protocol_id);
BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
head->protocol_id,head->protocol_id);
lp->stats.tx_errors++;
lp->stats.tx_aborted_errors++;
head->daddr=0;
......@@ -2938,7 +2930,7 @@ int arcnetS_rebuild_header(void *buff,struct device *dev,unsigned long dst,
if(head->protocol_id != ARC_P_IP_RFC1051)
{
printk("arcnetS: I don't understand protocol type %d (%Xh) addresses!\n",
BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
head->protocol_id,head->protocol_id);
lp->stats.tx_errors++;
lp->stats.tx_aborted_errors++;
......@@ -2996,7 +2988,7 @@ unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
case ARC_P_NOVELL_EC:
return htons(ETH_P_802_3);
default:
BUGMSG(D_EXTRA,"received packet of unknown protocol id %d (%Xh)\n",
BUGMSG(D_NORMAL,"received packet of unknown protocol id %d (%Xh)\n",
head->protocol_id,head->protocol_id);
lp->stats.rx_errors++;
lp->stats.rx_crc_errors++;
......@@ -3037,8 +3029,8 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP);
case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */
default:
BUGMSG(D_EXTRA,"received packet of unknown protocol id %d (%Xh)\n",
head->protocol_id,head->protocol_id);
BUGMSG(D_NORMAL,"received packet of unknown protocol id %d (%Xh)\n",
head->protocol_id,head->protocol_id);
lp->stats.rx_errors++;
lp->stats.rx_crc_errors++;
return 0;
......
......@@ -299,7 +299,12 @@ e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
mem_on(ioaddr, shared_mem, ring_page);
#ifdef notdef
/* Officially this is what we are doing, but the readl() is faster */
memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
#else
((unsigned int*)hdr)[0] = readl(shared_mem);
#endif
/* Turn off memory access: we would need to reprogram the window anyway. */
mem_off(ioaddr);
......
......@@ -34,6 +34,9 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/trdevice.h>
#ifdef CONFIG_NET_ALIAS
#include <linux/net_alias.h>
#endif
/* The network devices currently exist only in the socket namespace, so these
entries are unused. The only ones that make sense are
......@@ -293,6 +296,28 @@ void unregister_netdev(struct device *dev)
/* else */
if (dev->start)
printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
/*
* must jump over main_device+aliases
* avoid alias devices unregistration so that only
* net_alias module manages them
*/
#ifdef CONFIG_NET_ALIAS
if (dev_base == dev)
dev_base = net_alias_nextdev(dev);
else
{
while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */
d = net_alias_nextdev(d);
if (d && (net_alias_nextdev(d) == dev))
{
/*
* critical: bypass by consider devices as blocks (maindev+aliases)
*/
net_alias_nextdev_set(d, net_alias_nextdev(dev));
}
#else
if (dev_base == dev)
dev_base = dev->next;
else
......@@ -304,6 +329,7 @@ void unregister_netdev(struct device *dev)
{
d->next = dev->next;
}
#endif
else
{
printk("unregister_netdev: '%s' not found\n", dev->name);
......
......@@ -270,7 +270,12 @@ ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */
#ifdef notdef
/* Officially this is what we are doing, but the readl() is faster */
memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
#else
((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
}
......
......@@ -129,6 +129,13 @@ int wd_probe1(struct device *dev, int ioaddr)
dev = init_etherdev(0, 0);
}
/* Check for semi-valid mem_start/end values if supplied. */
if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
dev->mem_start = 0;
dev->mem_end = 0;
}
if (ei_debug && version_printed++ == 0)
printk(version);
......@@ -246,7 +253,7 @@ int wd_probe1(struct device *dev, int ioaddr)
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
if (request_irq(dev->irq, ei_interrupt, 0, "wd")) {
if (request_irq(dev->irq, ei_interrupt, 0, model_name)) {
printk (" unable to get IRQ %d.\n", dev->irq);
return EAGAIN;
}
......@@ -259,7 +266,7 @@ int wd_probe1(struct device *dev, int ioaddr)
}
/* OK, were are certain this is going to work. Setup the device. */
request_region(ioaddr, WD_IO_EXTENT,"wd");
request_region(ioaddr, WD_IO_EXTENT, model_name);
ei_status.name = model_name;
ei_status.word16 = word16;
......@@ -352,7 +359,12 @@ wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
if (ei_status.word16)
outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
#ifdef notdef
/* Officially this is what we are doing, but the readl() is faster */
memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
#else
((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
}
/* Block input and output are easy on shared memory ethercards, and trivial
......
......@@ -918,7 +918,7 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
ptr->host_scribble = NULL;
ptr->result = DID_ABORT << 16;
ptr->done(ptr);
ptr->scsi_done(ptr);
return SCSI_ABORT_SUCCESS;
}
......@@ -942,7 +942,7 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
/* target entered bus free before COMMAND COMPLETE, nothing to abort */
restore_flags(flags);
current_SC->result = DID_ERROR << 16;
current_SC->done(current_SC);
current_SC->scsi_done(current_SC);
current_SC = (Scsi_Cmnd *) NULL;
return SCSI_ABORT_SUCCESS;
}
......@@ -1063,7 +1063,7 @@ int aha152x_reset(Scsi_Cmnd * __unused)
{
current_SC->host_scribble = NULL;
current_SC->result = DID_RESET << 16;
current_SC->done(current_SC);
current_SC->scsi_done(current_SC);
current_SC=NULL;
}
......@@ -1083,7 +1083,7 @@ int aha152x_reset(Scsi_Cmnd * __unused)
ptr->host_scribble = NULL;
ptr->result = DID_RESET << 16;
ptr->done(ptr);
ptr->scsi_done(ptr);
ptr = next;
}
......
......@@ -23,6 +23,8 @@
#define CONST_XSENSE 0x08
#define CONST_CMND 0x10
#define CONST_MSG 0x20
#define CONST_HOST 0x40
#define CONST_DRIVER 0x80
static const char unknown[] = "UNKNOWN";
......@@ -30,7 +32,8 @@ static const char unknown[] = "UNKNOWN";
#ifdef CONSTANTS
#undef CONSTANTS
#endif
#define CONSTANTS (CONST_COMMAND | CONST_STATUS | CONST_SENSE | CONST_XSENSE | CONST_CMND | CONST_MSG)
#define CONSTANTS (CONST_COMMAND | CONST_STATUS | CONST_SENSE | CONST_XSENSE \
| CONST_CMND | CONST_MSG | CONST_HOST | CONST_DRIVER)
#endif
#if (CONSTANTS & CONST_COMMAND)
......@@ -568,6 +571,64 @@ void print_Scsi_Cmnd (Scsi_Cmnd *cmd) {
print_command (cmd->cmnd);
}
#if (CONSTANTS & CONST_HOST)
static const char * hostbyte_table[]={
"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",NULL};
void print_hostbyte(int scsiresult)
{ static int maxcode=0;
int i;
if(!maxcode) {
for(i=0;hostbyte_table[i];i++) ;
maxcode=i-1;
}
printk("Hostbyte=0x%02x",host_byte(scsiresult));
if(host_byte(scsiresult)>maxcode) {
printk("is invalid ");
return;
}
printk("(%s) ",hostbyte_table[host_byte(scsiresult)]);
}
#else
void print_hostbyte(int scsiresult)
{ printk("Hostbyte=0x%02x ",hostbyte(scsiresult));
}
#endif
#if (CONSTANTS & CONST_DRIVER)
static const char * driverbyte_table[]={
"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",NULL };
static const char * driversuggest_table[]={"SUGGEST_OK",
"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
unknown,unknown,unknown, "SUGGEST_SENSE",NULL};
void print_driverbyte(int scsiresult)
{ static int driver_max=0,suggest_max=0;
int i,dr=driver_byte(scsiresult)&DRIVER_MASK,
su=(driver_byte(scsiresult)&SUGGEST_MASK)>>4;
if(!driver_max) {
for(i=0;driverbyte_table[i];i++) ;
driver_max=i;
for(i=0;driversuggest_table[i];i++) ;
suggest_max=i;
}
printk("Driverbyte=0x%02x",driver_byte(scsiresult));
printk("(%s,%s) ",
dr<driver_max ? driverbyte_table[dr]:"invalid",
su<suggest_max ? driversuggest_table[su]:"invalid");
}
#else
void print_driverbyte(int scsiresult)
{ printk("Driverbyte=0x%02x ",driver_byte(scsiresult));
}
#endif
/*
* Overrides for Emacs so that we almost follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -65,6 +65,7 @@ static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid);
static int scan_scsis_single (int channel,int dev,int lun,int * max_scsi_dev ,
Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt,
struct Scsi_Host *shpnt, char * scsi_result);
void scsi_build_commandblocks(Scsi_Device * SDpnt);
static unsigned char * dma_malloc_freelist = NULL;
......@@ -272,18 +273,6 @@ static int get_device_flags(unsigned char * response_data){
return 0;
}
/*
* As the actual SCSI command runs in the background, we must set up a
* flag that tells scan_scsis() when the result it has is valid.
* scan_scsis can set the_result to -1, and watch for it to become the
* actual return code for that call. the scan_scsis_done function() is
* our user specified completion function that is passed on to the
* scsi_do_cmd() function.
*/
volatile int in_scan_scsis = 0;
static int the_result;
void scsi_make_blocked_list(void) {
int block_count = 0, index;
unsigned int flags;
......@@ -385,9 +374,10 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
int max_dev_lun;
Scsi_Cmnd *SCpnt;
in_scan_scsis++;
SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), GFP_ATOMIC | GFP_DMA);
SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC);
memset (SCpnt, 0, sizeof (Scsi_Cmnd));
/* Make sure we have something that is valid for DMA purposes */
scsi_result = ((!dma_malloc_freelist || !shpnt->unchecked_isa_dma)
......@@ -398,9 +388,17 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
goto leave;
}
shpnt->host_queue = SCpnt; /* We need this so that commands can time out */
/* We must chain ourself in the host_queue, so commands can time out */
if(shpnt->host_queue)
shpnt->host_queue->prev = SCpnt;
SCpnt->next = shpnt->host_queue;
SCpnt->prev = NULL;
shpnt->host_queue = SCpnt;
if (hardcoded == 1) {
Scsi_Device *oldSDpnt=SDpnt;
struct Scsi_Device_Template * sdtpnt;
channel = hchannel;
if(channel > shpnt->max_channel) goto leave;
dev = hid;
......@@ -409,11 +407,31 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
if(lun >= shpnt->max_lun) goto leave;
scan_scsis_single (channel, dev, lun, &max_dev_lun,
&SDpnt, SCpnt, shpnt, scsi_result);
if(SDpnt!=oldSDpnt) {
/* it could happen the blockdevice hasn't yet been inited */
for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();
oldSDpnt->scsi_request_fn = NULL;
for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
if(sdtpnt->attach) {
(*sdtpnt->attach)(oldSDpnt);
if(oldSDpnt->attached) scsi_build_commandblocks(oldSDpnt);}
resize_dma_pool();
for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
if(sdtpnt->finish && sdtpnt->nr_dev)
{(*sdtpnt->finish)();}
}
}
}
else {
for (channel = 0; channel <= shpnt->max_channel; channel++) {
for (dev = 0; dev < shpnt->max_id; ++dev) {
if (shpnt->this_id != dev) {
/*
* We need the for so our continue, etc. work fine. We put this in
* a variable so that we can override it during the scan if we
......@@ -421,20 +439,32 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
*/
max_dev_lun = (max_scsi_luns < shpnt->max_lun ?
max_scsi_luns : shpnt->max_lun);
for (lun = 0; lun < max_dev_lun; ++lun) {
if (!scan_scsis_single (channel, dev, lun, &max_dev_lun,
&SDpnt, SCpnt, shpnt, scsi_result))
break; /* break means don't probe for luns!=0 */
break; /* break means don't probe further for luns!=0 */
} /* for lun ends */
} /* if this_id != id ends */
} /* for dev ends */
} /* for channel ends */
leave:
shpnt->host_queue = NULL; /* No longer needed here */
} /* if/else hardcoded */
leave:
{/* Unchain SCpnt from host_queue */
Scsi_Cmnd *prev,*next,*hqptr;
for(hqptr=shpnt->host_queue; hqptr!=SCpnt; hqptr=hqptr->next) ;
if(hqptr) {
prev=hqptr->prev;
next=hqptr->next;
if(prev)
prev->next=next;
else
shpnt->host_queue=next;
if(next) next->prev=prev;
}
}
/* Last device block does not exist. Free memory. */
if (SDpnt != NULL)
scsi_init_free ((char *) SDpnt, sizeof (Scsi_Device));
......@@ -446,14 +476,12 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
if (scsi_result != &scsi_result0[0] && scsi_result != NULL)
scsi_free (scsi_result, 512);
in_scan_scsis--;
}
}
/*
* The worker for scan_scsis.
* Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
* Global variables used : scsi_devices(linked list), the_result
* Global variables used : scsi_devices(linked list)
*/
int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
Scsi_Device **SDpnt2, Scsi_Cmnd * SCpnt, struct Scsi_Host * shpnt,
......@@ -490,7 +518,6 @@ int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
scsi_cmd[1] = lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0;
memset (SCpnt, 0, sizeof (Scsi_Cmnd));
SCpnt->host = SDpnt->host;
SCpnt->device = SDpnt;
SCpnt->target = SDpnt->id;
......@@ -507,8 +534,10 @@ int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
}
#if defined(DEBUG) || defined(DEBUG_INIT)
printk ("scsi: scan_scsis_single id %d lun %d. Return code %d\n",
printk ("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n",
dev, lun, SCpnt->result);
print_driverbyte(SCpnt->result); print_hostbyte(SCpnt->result);
printk("\n");
#endif
if (SCpnt->result) {
......@@ -546,13 +575,12 @@ int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
down (&sem);
}
the_result = SCpnt->result;
#if defined(DEBUG) || defined(DEBUG_INIT)
printk ("scsi: INQUIRY %s with code 0x%x\n",
the_result ? "failed" : "successful", the->result);
SCpnt->result ? "failed" : "successful", SCpnt->result);
#endif
if (the_result)
if (SCpnt->result)
return 0; /* assume no peripheral if any sort of error */
/*
......@@ -696,7 +724,7 @@ int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC);
*SDpnt2=SDpnt;
if (!SDpnt)
printk ("scsi: scan_scsis_single: No memory\n");
printk ("scsi: scan_scsis_single: Cannot malloc\n");
/*
......@@ -750,7 +778,7 @@ static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid)
switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET))
{
case NORMAL_TIMEOUT:
if (!in_scan_scsis) {
{
#ifdef DEBUG_TIMEOUT
scsi_dump_status();
#endif
......@@ -1460,7 +1488,7 @@ static void scsi_done (Scsi_Cmnd * SCpnt)
printk ("Internal error %s %d \n", __FILE__,
__LINE__);
}
}
} /* end WAS_SENSE */
else
{
#ifdef DEBUG
......@@ -1734,8 +1762,7 @@ int scsi_abort (Scsi_Cmnd * SCpnt, int why, int pid)
SCpnt->internal_timeout |= IN_ABORT;
oldto = update_timeout(SCpnt, ABORT_TIMEOUT);
if ((SCpnt->flags & IS_RESETTING) &&
SCpnt->device->soft_reset) {
if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) {
/* OK, this command must have died when we did the
* reset. The device itself must have lied.
*/
......@@ -1797,6 +1824,8 @@ int scsi_abort (Scsi_Cmnd * SCpnt, int why, int pid)
/* We should have already aborted this one. No
* need to adjust timeout
*/
SCpnt->internal_timeout &= ~IN_ABORT;
return 0;
case SCSI_ABORT_NOT_RUNNING:
SCpnt->internal_timeout &= ~IN_ABORT;
update_timeout(SCpnt, 0);
......@@ -1837,10 +1866,8 @@ int scsi_reset (Scsi_Cmnd * SCpnt, int bus_reset_flag)
Scsi_Cmnd * SCpnt1;
struct Scsi_Host * host = SCpnt->host;
#ifdef DEBUG
printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",
printk("SCSI bus is being reset for host %d.\n",
host->host_no);
#endif
/*
* First of all, we need to make a recommendation to the low-level
......@@ -1862,10 +1889,8 @@ int scsi_reset (Scsi_Cmnd * SCpnt, int bus_reset_flag)
SCpnt1 = host->host_queue;
while(SCpnt1) {
if( SCpnt1->request.rq_status != RQ_INACTIVE
&& (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )
{
break;
}
&& (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )
break;
SCpnt1 = SCpnt1->next;
}
if( SCpnt1 == NULL ) {
......@@ -2154,7 +2179,7 @@ int scsi_free(void *obj, unsigned int len)
unsigned long flags;
#ifdef DEBUG
printk("Sfree %p %d\n",obj, len);
printk("scsi_free %p %d\n",obj, len);
#endif
offset = -1;
......@@ -2167,20 +2192,20 @@ int scsi_free(void *obj, unsigned int len)
break;
}
if (page == (dma_sectors >> 3)) panic("Bad offset");
if (page == (dma_sectors >> 3)) panic("scsi_free:Bad offset");
sector = offset >> 9;
if(sector >= dma_sectors) panic ("Bad page");
if(sector >= dma_sectors) panic ("scsi_free:Bad page");
sector = (offset >> 9) & (sizeof(*dma_malloc_freelist) * 8 - 1);
nbits = len >> 9;
mask = (1 << nbits) - 1;
if ((mask << sector) > 0xffff) panic ("Bad memory alignment");
if ((mask << sector) > 0xffff) panic ("scsi_free:Bad memory alignment");
save_flags(flags);
cli();
if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector))
panic("Trying to free unused memory");
panic("scsi_free:Trying to free unused memory");
dma_free_sectors += nbits;
dma_malloc_freelist[page] &= ~(mask << sector);
......@@ -2438,8 +2463,13 @@ int scsi_proc_info(char *buffer, char **start, off_t offset, int length,
/*
* Usage: echo "scsi singledevice 0 1 2 3" >/proc/scsi/scsi
* with "0 1 2 3" replaced by your "Host Channel Id Lun".
* Consider this feature ALPHA, as you can easily hang your
* scsi system (depending on your low level driver).
* Consider this feature BETA.
* CAUTION: This is not for hotplugging your peripherals. As
* SCSI was not designed for this you could damage your
* hardware !
* However perhaps it is legal to switch on an
* already connected device. It is perhaps not
* guaranteed this device doesn't corrupt an ongoing data transfer.
*/
if(!buffer || length < 25 || strncmp("scsi", buffer, 4))
return(-EINVAL);
......
......@@ -89,6 +89,7 @@ extern const unsigned char scsi_command_size[8];
#define DRIVER_INVALID 0x05
#define DRIVER_TIMEOUT 0x06
#define DRIVER_HARD 0x07
#define DRIVER_SENSE 0x08
#define SUGGEST_RETRY 0x10
#define SUGGEST_ABORT 0x20
......@@ -97,8 +98,6 @@ extern const unsigned char scsi_command_size[8];
#define SUGGEST_SENSE 0x80
#define SUGGEST_IS_OK 0xff
#define DRIVER_SENSE 0x08
#define DRIVER_MASK 0x0f
#define SUGGEST_MASK 0xf0
......@@ -448,6 +447,8 @@ extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
extern void print_command(unsigned char *);
extern void print_sense(const char *, Scsi_Cmnd *);
extern void print_driverbyte(int scsiresult);
extern void print_hostbyte(int scsiresult);
extern void scsi_mark_host_bus_reset(struct Scsi_Host *Host);
......
......@@ -59,7 +59,6 @@ struct symbol_table scsi_symbol_table = {
X(kernel_scsi_ioctl),
X(need_isa_buffer),
X(request_queueable),
X(in_scan_scsis),
#if defined(CONFIG_PROC_FS)
X(proc_print_scsidevice),
#endif
......
......@@ -1304,12 +1304,14 @@ static void sd_finish()
if (!rscsi_disks[i].capacity &&
rscsi_disks[i].device)
{
i = sd_init_onedisk(i);
if (MODULE_FLAG
&& !rscsi_disks[i].has_part_table) {
sd_sizes[i << 4] = rscsi_disks[i].capacity;
/* revalidate does sd_init_onedisk via MAYBE_REINIT*/
revalidate_scsidisk(MKDEV(MAJOR_NR, i << 4), 0);
}
else
i=sd_init_onedisk(i);
rscsi_disks[i].has_part_table = 1;
}
......
......@@ -297,7 +297,8 @@ int mem_mmap(struct inode * inode, struct file * file,
dtmp += PAGE_SIZE;
}
invalidate();
invalidate_range(vma->vm_mm, vma->vm_start, vma->vm_end);
invalidate_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end);
return 0;
}
......
......@@ -91,13 +91,13 @@ struct vfsmount *add_vfsmnt(kdev_t dev, const char *dev_name, const char *dir_na
lptr->mnt_sem.count = 1;
if (dev_name && !getname(dev_name, &tmp)) {
if ((lptr->mnt_devname =
(char *) kmalloc(strlen(tmp), GFP_KERNEL)) != (char *)NULL)
(char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
strcpy(lptr->mnt_devname, tmp);
putname(tmp);
}
if (dir_name && !getname(dir_name, &tmp)) {
if ((lptr->mnt_dirname =
(char *) kmalloc(strlen(tmp), GFP_KERNEL)) != (char *)NULL)
(char *) kmalloc(strlen(tmp)+1, GFP_KERNEL)) != (char *)NULL)
strcpy(lptr->mnt_dirname, tmp);
putname(tmp);
}
......
......@@ -26,32 +26,81 @@
* - invalidate_page(mm, vmaddr) invalidates one page
* - invalidate_range(mm, start, end) invalidates a range of pages
*
* ..but the i386 has somewhat limited invalidation capabilities.
* ..but the i386 has somewhat limited invalidation capabilities,
* and page-granular invalidates are available only on i486 and up.
*/
#define __invalidate() \
__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
#ifdef __i486__
#define __invalidate_one(addr) \
__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
#else
#define __invalidate_one(addr) invalidate()
#endif
#ifndef __SMP__
#define invalidate() \
__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
#define invalidate() __invalidate()
#define invalidate_all() __invalidate()
static inline void invalidate_mm(struct mm_struct *mm)
{
if (mm == current->mm)
__invalidate();
}
static inline void invalidate_page(struct mm_struct *mm,
unsigned long addr)
{
if (mm == current->mm)
__invalidate_one(addr);
}
static inline void invalidate_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
if (mm == current->mm)
__invalidate();
}
#else
/*
* We aren't very clever about this yet - SMP could certainly
* avoid some global invalidates..
*/
#include <asm/smp.h>
#define local_invalidate() \
__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
__invalidate()
#define invalidate() \
smp_invalidate();
#endif
smp_invalidate()
/*
* We aren't very clever about this yet. On a 486+ we could actually do
* page-granularity invalidates for better performance in some cases.
* And SMP could certainly avoid some global invalidates..
*/
#define invalidate_all() invalidate()
#define invalidate_mm(mm_struct) \
do { if ((mm_struct) == current->mm) invalidate(); } while (0)
#define invalidate_page(mm_struct,addr) \
do { if ((mm_struct) == current->mm) invalidate(); } while (0)
#define invalidate_range(mm_struct,start,end) \
do { if ((mm_struct) == current->mm) invalidate(); } while (0)
static inline void invalidate_mm(struct mm_struct *mm)
{
invalidate();
}
static inline void invalidate_page(struct mm_struct *mm,
unsigned long addr)
{
invalidate();
}
static inline void invalidate_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
invalidate();
}
#endif
/* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
......
#ifndef _NET_ALIAS_H
#define _NET_ALIAS_H
#include <linux/types.h>
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/inet.h>
#include <linux/in.h> /* for default IP behavior */
/*
* max. alias slot number allowed
*/
#define NET_ALIAS_MAX_SLOT 256
struct net_alias;
struct net_alias_info;
struct net_alias_type;
/*
* main alias structure
* note that *defines* dev & devname
*/
struct net_alias
{
struct device dev; /* alias device defn*/
char name[IFNAMSIZ]; /* device name defn */
unsigned hash; /* my hash value: for quick rehash */
unsigned slot; /* slot number */
void *data; /* private data */
struct device *main_dev; /* pointer to main device */
struct net_alias_type *nat; /* alias type bound */
struct net_alias *next; /* next alias (hashed linked list) */
};
/*
* alias structure pointed by main device
* it holds main device's alias hash table
*/
struct net_alias_info
{
int n_aliases; /* num aliases */
struct device *taildev; /* my last (alias) device */
struct net_alias *hash_tab[16]; /* hashed alias table */
};
/*
* net_alias_type class
* declares a generic (AF_ independent) structure that will
* manage generic to family-specific behavior.
*/
struct net_alias_type
{
int type; /* aliasing type: address family */
int n_attach; /* number of aliases attached */
char name[16]; /* af_name */
__u32 (*get_addr32) /* get __u32 addr 'representation'*/
(struct sockaddr*);
int (*addr_chk) /* address checking func: */
(struct device *, struct sockaddr *);
int (*alias_init_1) /* called after alias creation: */
(struct net_alias *alias, struct sockaddr *sa);
int (*alias_done_1) /* called before alias deletion */
(struct net_alias *alias);
int (*alias_print_1)
(char *buf, int len, struct net_alias *alias);
struct net_alias_type *next; /* link */
};
/*
* is dev an alias?
*/
static __inline__ int
net_alias_is(struct device *dev)
{
return (dev->my_alias != 0);
}
/*
* does dev have aliases?
*/
static __inline__ int
net_alias_has(struct device *dev)
{
return (dev->alias_info != 0);
}
extern void net_alias_init(void);
extern struct device * net_alias_dev_get(char *dev_name, int aliasing_ok, int *err, struct sockaddr *sa, void *data);
extern int net_alias_rehash(struct net_alias *alias, struct sockaddr *sa);
extern int net_alias_getinfo(char *buf, char **, off_t , int , int );
extern int net_alias_types_getinfo(char *buf, char **, off_t , int , int );
extern int register_net_alias_type(struct net_alias_type *nat, int type);
extern int unregister_net_alias_type(struct net_alias_type *nat);
extern struct device * net_alias_chk(struct device *dev, struct sockaddr *sa, int flags_1, int flags_0);
extern struct device * net_alias_chk32(struct device *dev, int family, __u32 addr32, int flags_1, int flags_0);
/*
* returns MY 'true' main device
* intended for alias devices
*/
static __inline__ struct device *net_alias_main_dev(struct device *dev)
{
return (net_alias_is(dev))? dev->my_alias->main_dev : dev;
}
/*
* returns NEXT 'true' device
* intended for true devices
*/
static __inline__ struct device *
net_alias_nextdev(struct device *dev)
{
return (dev->alias_info)? dev->alias_info->taildev->next : dev->next;
}
/*
* sets NEXT 'true' device
* intended for main devices (treat main device as block: dev+aliases).
*/
static __inline__ struct device *
net_alias_nextdev_set(struct device *dev, struct device *nextdev)
{
struct device *pdev = dev;
if (net_alias_has(dev))
{
pdev = dev->alias_info->taildev; /* point to last dev alias */
}
pdev->next = nextdev;
return nextdev;
}
/*
* addr_chk wrapper: check given generic address with (UP) aliases
*/
static __inline__ struct device *
net_alias_addr_chk(struct device *dev, struct sockaddr *sa)
{
return net_alias_chk(dev, sa, IFF_UP, 0);
}
/*
* addr_chk32 wrapper: check given u32 address with (UP) aliases
*/
static __inline__ struct device *
net_alias_addr_chk32(struct device *dev, int family, __u32 addr32)
{
return net_alias_chk32(dev, family, addr32, IFF_UP, 0);
}
#endif /* _NET_ALIAS_H */
......@@ -152,6 +152,8 @@ struct device
unsigned long pkt_queue; /* Packets queued */
struct device *slave; /* Slave device */
struct net_alias_info *alias_info; /* main dev alias info */
struct net_alias *my_alias; /* alias devs */
/* Pointer to the interface buffers. */
......
......@@ -89,6 +89,8 @@ enum net_directory_inos {
PROC_NET_SOCKSTAT,
PROC_NET_RTCACHE,
PROC_NET_AX25_BPQETHER,
PROC_NET_ALIAS_TYPES,
PROC_NET_ALIASES,
PROC_NET_LAST
};
......
......@@ -44,8 +44,8 @@ struct rlimit {
long rlim_max;
};
#define PRIO_MIN (-99)
#define PRIO_MAX 14
#define PRIO_MIN (-20)
#define PRIO_MAX 20
#define PRIO_PROCESS 0
#define PRIO_PGRP 1
......
......@@ -48,5 +48,7 @@ struct vt_consize {
ushort v_ccol; /* number of pixel columns per character */
};
#define VT_RESIZEX 0x560A /* set kernel's idea of screensize + more */
#define VT_LOCKSWITCH 0x560B /* disallow vt switching */
#define VT_UNLOCKSWITCH 0x560C /* allow vt switching */
#endif /* _LINUX_VT_H */
#ifndef _IP_ALIAS_H
#define _IP_ALIAS_H
/*
* IP alias specific prototypes
*/
#include <linux/net_alias.h>
extern int ip_alias_init(void);
extern int ip_alias_done(void);
#endif /* _IP_ALIAS_H */
......@@ -445,7 +445,7 @@ static int shm_map (struct vm_area_struct *shmd)
return -ENOMEM;
set_pte(page_table, __pte(shm_sgn));
}
invalidate();
invalidate_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
return 0;
}
......@@ -680,7 +680,7 @@ int shm_swap (int prio, unsigned long limit)
struct vm_area_struct *shmd;
unsigned long swap_nr;
unsigned long id, idx;
int loop = 0, invalid = 0;
int loop = 0;
int counter;
counter = shm_rss >> prio;
......@@ -716,8 +716,6 @@ int shm_swap (int prio, unsigned long limit)
if (--counter < 0) { /* failed */
failed:
if (invalid)
invalidate();
swap_free (swap_nr);
return 0;
}
......@@ -766,7 +764,7 @@ int shm_swap (int prio, unsigned long limit)
mem_map[MAP_NR(pte_page(pte))].count--;
if (shmd->vm_mm->rss > 0)
shmd->vm_mm->rss--;
invalid++;
invalidate_range(shmd->vm_mm, shmd->vm_start, shmd->vm_end);
/* continue looping through circular list */
} while (0);
if ((shmd = shmd->vm_next_share) == shp->attaches)
......@@ -776,8 +774,6 @@ int shm_swap (int prio, unsigned long limit)
if (mem_map[MAP_NR(pte_page(page))].count != 1)
goto check_table;
shp->shm_pages[idx] = swap_nr;
if (invalid)
invalidate();
write_swap_page (swap_nr, (char *) pte_page(page));
free_page(pte_page(page));
swap_successes++;
......
......@@ -76,6 +76,9 @@ extern void __remqu (void);
#include "../drivers/net/slhc.h"
#endif
#endif
#ifdef CONFIG_NET_ALIAS
#include <linux/net_alias.h>
#endif
#endif
#ifdef CONFIG_PCI
#include <linux/bios32.h>
......@@ -412,6 +415,10 @@ struct symbol_table symbol_table = {
/* Device callback registration */
X(register_netdevice_notifier),
X(unregister_netdevice_notifier),
#ifdef CONFIG_NET_ALIAS
X(register_net_alias_type),
X(unregister_net_alias_type),
#endif
#endif
/* support for loadable net drivers */
......@@ -452,11 +459,7 @@ struct symbol_table symbol_table = {
* So we add it here too. There is a duplicate set in scsi.c
* that is used when the entire scsi subsystem is a loadable
* module.
*
* in_scan_scsis is a hack, and should go away once the new
* memory allocation code is in the NCR driver
*/
X(in_scan_scsis),
X(scsi_register_module),
X(scsi_unregister_module),
X(scsi_free),
......
......@@ -141,7 +141,8 @@ int filemap_swapout(struct vm_area_struct * vma,
unsigned long entry = SWP_ENTRY(SHM_SWP_TYPE, MAP_NR(page));
set_pte(page_table, __pte(entry));
invalidate();
/* Yuck, perhaps a slightly modified swapout parameter set? */
invalidate_page(vma->vm_mm, (offset + vma->vm_start - vma->vm_offset));
error = filemap_write_page(vma, offset, page);
if (pte_val(*page_table) == entry)
pte_clear(page_table);
......@@ -179,13 +180,14 @@ static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
if (!pte_dirty(pte))
return 0;
set_pte(ptep, pte_mkclean(pte));
invalidate_page(vma->vm_mm, address);
page = pte_page(pte);
mem_map[MAP_NR(page)].count++;
} else {
if (pte_none(pte))
return 0;
pte_clear(ptep);
invalidate();
invalidate_page(vma->vm_mm, address);
if (!pte_present(pte)) {
swap_free(pte_val(pte));
return 0;
......@@ -274,7 +276,7 @@ static int filemap_sync(struct vm_area_struct * vma, unsigned long address,
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_range(vma->vm_mm, end - size, end);
return error;
}
......
......@@ -134,7 +134,7 @@ void clear_page_tables(struct task_struct * tsk)
}
for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
free_one_pgd(page_dir + i);
invalidate();
invalidate_mm(tsk->mm);
}
/*
......@@ -153,12 +153,12 @@ void free_page_tables(struct task_struct * tsk)
printk("%s trying to free kernel page-directory: not good\n", tsk->comm);
return;
}
invalidate_mm(tsk->mm);
SET_PAGE_DIR(tsk, swapper_pg_dir);
tsk->mm->pgd = swapper_pg_dir; /* or else... */
for (i = 0 ; i < PTRS_PER_PGD ; i++)
free_one_pgd(page_dir + i);
pgd_free(page_dir);
invalidate();
}
int new_page_tables(struct task_struct * tsk)
......@@ -171,6 +171,7 @@ int new_page_tables(struct task_struct * tsk)
page_dir = pgd_offset(&init_mm, 0);
for (i = USER_PTRS_PER_PGD ; i < PTRS_PER_PGD ; i++)
new_pg[i] = page_dir[i];
invalidate_mm(tsk->mm);
SET_PAGE_DIR(tsk, new_pg);
tsk->mm->pgd = new_pg;
return 0;
......@@ -285,7 +286,9 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
break;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
}
invalidate();
/* Note that the src ptes get c-o-w treatment, so they change too. */
invalidate_range(src, vma->vm_start, vma->vm_end);
invalidate_range(dst, vma->vm_start, vma->vm_end);
return error;
}
......@@ -369,7 +372,7 @@ int zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long si
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_range(mm, end - size, end);
return 0;
}
......@@ -429,7 +432,7 @@ int zeromap_page_range(unsigned long address, unsigned long size, pgprot_t prot)
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_range(current->mm, end - size, end);
return error;
}
......@@ -499,7 +502,7 @@ int remap_page_range(unsigned long from, unsigned long offset, unsigned long siz
from = (from + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_range(current->mm, from - size, from);
return error;
}
......@@ -514,7 +517,7 @@ static void put_page(pte_t * page_table, pte_t pte)
return;
}
/* no need for invalidate */
*page_table = pte;
set_pte(page_table, pte);
}
/*
......@@ -547,7 +550,7 @@ unsigned long put_dirty_page(struct task_struct * tsk, unsigned long page, unsig
if (!pte_none(*pte)) {
printk("put_dirty_page: page already exists\n");
pte_clear(pte);
invalidate();
invalidate_page(tsk->mm, address);
}
set_pte(pte, pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY))));
/* no need for invalidate */
......@@ -610,17 +613,17 @@ void do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma,
copy_page(old_page,new_page);
set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
free_page(old_page);
invalidate();
invalidate_page(vma->vm_mm, address);
return;
}
set_pte(page_table, BAD_PAGE);
free_page(old_page);
oom(tsk);
invalidate();
invalidate_page(vma->vm_mm, address);
return;
}
set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
invalidate();
invalidate_page(vma->vm_mm, address);
if (new_page)
free_page(new_page);
return;
......@@ -842,7 +845,7 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
return 1;
/* ok, need to mark it read-only, so invalidate any possible old TB entry */
set_pte(from_table, pte_wrprotect(from));
invalidate();
invalidate_page(from_area->vm_mm, from_address);
return 1;
}
......
......@@ -72,6 +72,7 @@ static inline void change_pmd_range(pgd_t * pgd, unsigned long address,
static void change_protection(unsigned long start, unsigned long end, pgprot_t newprot)
{
pgd_t *dir;
unsigned long beg = start;
dir = pgd_offset(current->mm, start);
while (start < end) {
......@@ -79,7 +80,7 @@ static void change_protection(unsigned long start, unsigned long end, pgprot_t n
start = (start + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_range(current->mm, beg, end);
return;
}
......
......@@ -457,7 +457,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
return 0;
vma->vm_mm->rss--;
set_pte(page_table, __pte(entry));
invalidate();
invalidate_page(vma->vm_mm, address);
tsk->nswap++;
write_swap_page(entry, (char *) page);
}
......@@ -472,13 +472,13 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
}
vma->vm_mm->rss--;
set_pte(page_table, __pte(entry));
invalidate();
invalidate_page(vma->vm_mm, address);
free_page(page);
return 1;
}
vma->vm_mm->rss--;
pte_clear(page_table);
invalidate();
invalidate_page(vma->vm_mm, address);
entry = mem_map[MAP_NR(page)].count;
free_page(page);
return entry;
......
......@@ -105,7 +105,7 @@ static void free_area_pages(unsigned long address, unsigned long size)
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_all();
}
static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size)
......@@ -166,7 +166,7 @@ static int alloc_area_pages(unsigned long address, unsigned long size)
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_all();
return 0;
}
......@@ -227,7 +227,7 @@ static int remap_area_pages(unsigned long address, unsigned long offset, unsigne
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
}
invalidate();
invalidate_all();
return 0;
}
......
......@@ -4,6 +4,7 @@
mainmenu_option next_comment
comment 'Networking options'
bool 'Network firewalls' CONFIG_FIREWALL
bool 'Network aliasing' CONFIG_NET_ALIAS
bool 'TCP/IP networking' CONFIG_INET
if [ "$CONFIG_INET" = "y" ]; then
source net/ipv4/Config.in
......
......@@ -19,6 +19,10 @@ ifdef CONFIG_FIREWALL
O_OBJS += firewall.o
endif
ifdef CONFIG_NET_ALIAS
O_OBJS += net_alias.o
endif
endif
include $(TOPDIR)/Rules.make
......
......@@ -70,6 +70,9 @@
#include <net/arp.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#ifdef CONFIG_NET_ALIAS
#include <linux/net_alias.h>
#endif
/*
* The list of packet types we will receive (as opposed to discard)
......@@ -356,6 +359,19 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
return;
}
/*
*
* If dev is an alias, switch to its main device.
* "arp" resolution has been made with alias device, so
* arp entries refer to alias, not main.
*
*/
#ifdef CONFIG_NET_ALIAS
if (net_alias_is(dev))
skb->dev = dev = net_alias_main_dev(dev);
#endif
save_flags(flags);
cli();
if (!where) /* Always keep order. It helps other hosts
......@@ -561,7 +577,7 @@ void dev_transmit(void)
{
struct device *dev;
for (dev = dev_base; dev != NULL; dev = dev->next)
for (dev = dev_base; dev != NULL; dev = dev->next)
{
if (dev->flags != 0 && !dev->tbusy) {
/*
......@@ -753,6 +769,13 @@ void dev_tint(struct device *dev)
struct sk_buff *skb;
unsigned long flags;
/*
* aliases do not trasmit (by now :)
*/
#ifdef CONFIG_NET_ALIAS
if (net_alias_is(dev)) return;
#endif
save_flags(flags);
/*
* Work the queues in priority order
......@@ -984,9 +1007,20 @@ static int dev_ifsioc(void *arg, unsigned int getset)
* See which interface the caller is talking about.
*/
/*
*
* net_alias_dev_get(): dev_get() with added alias naming magic.
* only allow alias creation/deletion if (getset==SIOCSIFADDR)
*
*/
#ifdef CONFIG_NET_ALIAS
if ((dev = net_alias_dev_get(ifr.ifr_name, getset == SIOCSIFADDR, &err, NULL, NULL)) == NULL)
return(err);
#else
if ((dev = dev_get(ifr.ifr_name)) == NULL)
return(-ENODEV);
#endif
switch(getset)
{
case SIOCGIFFLAGS: /* Get interface flags */
......@@ -1079,6 +1113,16 @@ static int dev_ifsioc(void *arg, unsigned int getset)
}
else
{
/*
* if dev is an alias, must rehash to update
* address change
*/
#ifdef CONFIG_NET_ALIAS
if (net_alias_is(dev))
net_alias_rehash(dev->my_alias,&ifr.ifr_addr);
#endif
dev->pa_addr = (*(struct sockaddr_in *)
&ifr.ifr_addr).sin_addr.s_addr;
dev->family = ifr.ifr_addr.sa_family;
......@@ -1382,6 +1426,18 @@ int net_dev_init(void)
dev_get_info
});
/*
* Initialise net_alias engine
*
* - register net_alias device notifier
* - register proc entries: /proc/net/alias_types
* /proc/net/aliases
*/
#ifdef CONFIG_NET_ALIAS
net_alias_init();
#endif
bh_base[NET_BH].routine = net_bh;
enable_bh(NET_BH);
return 0;
......
/*
* NET_ALIAS device aliasing module.
*
* Version: @(#)net_alias.c 0.42 12/11/95
*
* Authors: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
* Marcelo Fabian Roccasalva, <mfroccas@raiz.uncu.edu.ar>
*
* Features:
* - AF_ independent: net_alias_type objects
* - AF_INET optimized
* - ACTUAL alias devices inserted in dev chain
* - fast hashed alias address lookup
* - net_alias_type objs registration/unreg., module-ables.
* - /proc/net/aliases & /proc/net/alias_types entries
*
* FIXME:
* - User calls sleep/wake_up locking.
* - Define a way to select the "best" alias device for an incoming
* packet to allow xxx_rcv() device switching based ALSO on pkt's
* src address (this would require a routing query).
* Related stuff:
* IP: Test routing between aliases (possible ICMP redirects).
* IP: ARP proxy entries attached to aliases are not visible.
*
*
* 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 Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/if.h>
#include <linux/inet.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#ifdef ALIAS_USER_LAND_DEBUG
#include "net_alias.h"
#include "user_stubs.h"
#endif
#include <linux/net_alias.h>
/*
* Only allow the following flags to pass from main device to aliases
*/
#define NET_ALIAS_IFF_MASK (IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_NOARP|IFF_LOOPBACK|IFF_POINTOPOINT)
static struct net_alias_type * nat_getbytype(int type);
static int nat_attach_chg(struct net_alias_type *nat, int delta);
static int nat_bind(struct net_alias_type *nat,struct net_alias *alias, struct sockaddr *sa);
static int nat_unbind(struct net_alias_type *nat, struct net_alias *alias);
static int net_alias_devinit(struct device *dev);
static int net_alias_hard_start_xmit(struct sk_buff *skb, struct device *dev);
static int net_alias_devsetup(struct net_alias *alias, struct net_alias_type *nat, struct sockaddr *sa);
static struct net_alias **net_alias_slow_findp(struct net_alias_info *alias_info, struct net_alias *alias);
static struct device *net_alias_dev_create(struct device *main_dev, int slot, int *err, struct sockaddr *sa, void *data);
static struct device *net_alias_dev_delete(struct device *main_dev, int slot, int *err);
static void net_alias_free(struct device *dev);
/*
* net_alias_type base array, will hold net_alias_type objects.
*/
struct net_alias_type *nat_base[16];
/*
* get net_alias_type ptr by type
*/
static __inline__ struct net_alias_type *
nat_getbytype(int type)
{
struct net_alias_type *nat;
for(nat = nat_base[type & 0x0f]; nat ; nat = nat->next)
{
if (nat->type == type) return nat;
}
return NULL;
}
/*
* get addr32 representation (pre-hashing) of address.
* if NULL nat->get_addr32, assume sockaddr_in struct (IP-ish).
*/
static __inline__ __u32
nat_addr32(struct net_alias_type *nat, struct sockaddr *sa)
{
if (nat->get_addr32)
return nat->get_addr32(sa);
else
return (*(struct sockaddr_in *)sa).sin_addr.s_addr;
}
/*
* hashing code for alias_info->hash_tab entries
* 4 bytes -> 1/2 byte using xor condimented by af
*/
static __inline__ unsigned
HASH(__u32 addr, int af)
{
unsigned tmp = addr ^ (addr>>16); /* 4 -> 2 */
tmp ^= (tmp>>8); /* 2 -> 1 */
return (tmp^(tmp>>4)^af) & 0x0f; /* 1 -> 1/2 */
}
/*
* get hash key for supplied net alias type and address
* nat must be !NULL
* the purpose here is to map an net_alias_type and a generic
* address to a hash code.
*/
static __inline__ int
nat_hash_key(struct net_alias_type *nat, struct sockaddr *sa)
{
return HASH(nat_addr32(nat,sa), sa->sa_family);
}
/*
* change net_alias_type number of attachments (bindings)
*/
static int
nat_attach_chg(struct net_alias_type *nat, int delta)
{
unsigned long flags;
int n_at;
if (!nat) return -1;
save_flags(flags);
cli();
n_at = nat->n_attach + delta;
if (n_at < 0)
{
restore_flags(flags);
printk("net_alias: tried to set n_attach < 0 for (family==%d) nat object.\n",
nat->type);
return -1;
}
nat->n_attach = n_at;
restore_flags(flags);
return 0;
}
/*
* bind alias to its type (family) object and call initialization hook
*/
static __inline__ int
nat_bind(struct net_alias_type *nat,struct net_alias *alias, struct sockaddr *sa)
{
if (nat->alias_init_1) nat->alias_init_1(alias, sa);
return nat_attach_chg(nat, +1);
}
/*
* unbind alias from type object and call 'done' hook
*/
static __inline__ int
nat_unbind(struct net_alias_type *nat, struct net_alias *alias)
{
if (nat->alias_done_1) nat->alias_done_1(alias);
return nat_attach_chg(nat, -1);
}
/*
* compare device address with given. if NULL nat->addr_chk,
* compare dev->pa_addr with (sockaddr_in) 32 bits address (IP-ish)
*/
static __inline__ int nat_addr_chk(struct net_alias_type *nat,
struct device *dev, struct sockaddr *sa)
{
if (nat->addr_chk)
return nat->addr_chk(dev, sa);
else
return (dev->pa_addr == (*(struct sockaddr_in *)sa).sin_addr.s_addr);
}
/*
* alias device init()
* do nothing.
*/
static int
net_alias_devinit(struct device *dev)
{
#ifdef ALIAS_USER_LAND_DEBUG
printk("net_alias_devinit(%s) called.\n", dev->name);
#endif
return 0;
}
/*
* hard_start_xmit() should not be called.
* ignore ... but shout!.
*/
static int
net_alias_hard_start_xmit(struct sk_buff *skb, struct device *dev)
{
printk("net_alias: net_alias_hard_start_xmit() for %s called (ignored)!!\n", dev->name);
dev_kfree_skb(skb, FREE_WRITE);
return 0;
}
/*
* setups a new (alias) device
*/
static int
net_alias_devsetup(struct net_alias *alias, struct net_alias_type *nat,
struct sockaddr *sa)
{
struct device *main_dev;
struct device *dev;
int family;
int i;
/*
*
* generic device setup based on main_dev info
*
* FIXME: is NULL bitwise 0 for all Linux platforms?
*/
main_dev = alias->main_dev;
dev = &alias->dev;
memset(dev, '\0', sizeof(struct device));
family = (sa)? sa->sa_family : main_dev->family;
dev->alias_info = NULL; /* no aliasing recursion */
dev->my_alias = alias; /* point to alias */
dev->name = alias->name;
dev->type = main_dev->type;
dev->hard_header_len = main_dev->hard_header_len;
memcpy(dev->broadcast, main_dev->broadcast, MAX_ADDR_LEN);
memcpy(dev->dev_addr, main_dev->dev_addr, MAX_ADDR_LEN);
dev->addr_len = main_dev->addr_len;
dev->init = net_alias_devinit;
dev->hard_start_xmit = net_alias_hard_start_xmit;
dev->flags = main_dev->flags & NET_ALIAS_IFF_MASK & ~IFF_UP;
/*
* only makes sense if same family
*/
if (family == main_dev->family)
{
dev->metric = main_dev->metric;
dev->mtu = main_dev->mtu;
dev->pa_alen = main_dev->pa_alen;
dev->hard_header = main_dev->hard_header;
dev->rebuild_header = main_dev->rebuild_header;
}
/*
* Fill in the generic fields of the device structure.
* not actually used, avoids some dev.c #ifdef's
*/
for (i = 0; i < DEV_NUMBUFFS; i++)
skb_queue_head_init(&dev->buffs[i]);
dev->family = family;
return 0;
}
/*
* slow alias find (parse the whole hash_tab)
* returns: alias' pointer address
*/
static struct net_alias **
net_alias_slow_findp(struct net_alias_info *alias_info, struct net_alias *alias)
{
unsigned idx, n_aliases;
struct net_alias **aliasp;
/*
* for each alias_info's hash_tab entry, for every alias ...
*/
n_aliases = alias_info->n_aliases;
for (idx=0; idx < 16 ; idx++)
for (aliasp = &alias_info->hash_tab[idx];*aliasp;aliasp = &(*aliasp)->next)
if (*aliasp == alias)
return aliasp;
else
if (--n_aliases == 0) break; /* faster give up */
return NULL;
}
/*
* create alias device for main_dev with given slot num.
* if sa==NULL will create a same_family alias device
*/
static struct device *
net_alias_dev_create(struct device *main_dev, int slot, int *err, struct sockaddr *sa, void *data)
{
struct net_alias_info *alias_info;
struct net_alias *alias, **aliasp;
struct net_alias_type *nat;
struct device *dev;
unsigned long flags;
int family;
__u32 addr32;
/* FIXME: lock */
alias_info = main_dev->alias_info;
/*
* if NULL address given, take family from main_dev
*/
family = (sa)? sa->sa_family : main_dev->family;
/*
* check if wanted family has a net_alias_type object registered
*/
nat = nat_getbytype(family);
if (!nat)
{
printk("net_alias_dev_create(%s:%d): unregistered family==%d\n",
main_dev->name, slot, family);
/* *err = -EAFNOSUPPORT; */
*err = -EINVAL;
return NULL;
}
/*
* do not allow creation over downed devices
*/
*err = -EIO;
if (! (main_dev->flags & IFF_UP) )
return NULL;
/*
* if first alias, must also create alias_info
*/
*err = -ENOMEM;
if (!alias_info)
{
alias_info = kmalloc(sizeof(struct net_alias_info), GFP_KERNEL);
if (!alias_info) return NULL; /* ENOMEM */
memset(alias_info, 0, sizeof(struct net_alias_info));
}
if (!(alias = kmalloc(sizeof(struct net_alias), GFP_KERNEL)))
return NULL; /* ENOMEM */
/*
* FIXME: is NULL bitwise 0 for all Linux platforms?
*/
memset(alias, 0, sizeof(struct net_alias));
alias->slot = slot;
alias->main_dev = main_dev;
alias->nat = nat;
alias->next = NULL;
alias->data = data;
sprintf(alias->name, "%s:%d", main_dev->name, slot);
/*
* initialise alias' device structure
*/
net_alias_devsetup(alias, nat, sa);
dev = &alias->dev;
save_flags(flags);
cli();
/*
* bind alias to its object type
* nat_bind calls nat->alias_init_1
*/
nat_bind(nat, alias, sa);
/*
* if no address passed, take from device (could have been
* set by nat->alias_init_1)
*/
addr32 = (sa)? nat_addr32(nat, sa) : alias->dev.pa_addr;
/*
* store hash key in alias: will speed-up rehashing and deletion
*/
alias->hash = HASH(addr32, family);
/*
* insert alias in hashed linked list
*/
aliasp = &alias_info->hash_tab[alias->hash];
alias->next = *aliasp;
*aliasp = alias;
/*
* if first alias ...
*/
if (!alias_info->n_aliases++)
{
alias_info->taildev = main_dev;
main_dev->alias_info = alias_info;
}
/*
* add device at tail (just after last main_dev alias)
*/
dev->next = alias_info->taildev->next;
alias_info->taildev->next = dev;
alias_info->taildev = dev;
restore_flags(flags);
return dev;
}
/*
* delete one main_dev alias (referred by its slot num)
*/
static struct device *
net_alias_dev_delete(struct device *main_dev, int slot, int *err)
{
struct net_alias_info *alias_info;
struct net_alias *alias, **aliasp;
struct device *dev;
unsigned n_aliases;
unsigned long flags;
struct net_alias_type *nat;
struct device *prevdev;
/* FIXME: lock */
*err = -ENODEV;
if (main_dev == NULL) return NULL;
/*
* does main_dev have aliases?
*/
alias_info = main_dev->alias_info;
if (!alias_info) return NULL; /* ENODEV */
n_aliases = alias_info->n_aliases;
/*
* find device that holds the same slot number (could also
* be strcmp() ala dev_get).
*/
for (prevdev=main_dev, alias = NULL;prevdev->next && n_aliases; prevdev = prevdev->next)
{
if (!(alias = prevdev->next->my_alias))
{
printk("ERROR: net_alias_dev_delete(): incorrect non-alias device after maindev\n");
continue; /* or should give up? */
}
if (alias->slot == slot) break;
alias = NULL;
n_aliases--;
}
if (!alias) return NULL; /* ENODEV */
dev = &alias->dev;
/*
* find alias hashed entry
*/
for(aliasp = &alias_info->hash_tab[alias->hash]; *aliasp; aliasp = &(*aliasp)->next)
if(*aliasp == alias) break;
/*
* if not found (???), try a full search
*/
if (*aliasp != alias)
if ((aliasp = net_alias_slow_findp(alias_info, alias)))
printk("net_alias_dev_delete(%s): bad hashing recovered\n", alias->name);
else
{
printk("ERROR: net_alias_dev_delete(%s): unhashed alias!\n",alias->name);
return NULL; /* ENODEV */
}
nat = alias->nat;
save_flags(flags);
cli();
/*
* unbind alias from alias_type obj.
*/
nat_unbind(nat, alias);
/*
* is alias at tail?
*/
if ( dev == alias_info->taildev )
alias_info->taildev = prevdev;
/*
* unlink and close device
*/
prevdev->next = dev->next;
dev_close(dev);
/*
* unlink alias
*/
*aliasp = (*aliasp)->next;
if (--alias_info->n_aliases == 0) /* last alias */
main_dev->alias_info = NULL;
restore_flags(flags);
/*
* now free structures
*/
kfree_s(alias, sizeof(struct net_alias));
if (main_dev->alias_info == NULL)
kfree_s(alias_info, sizeof(struct net_alias_info));
/*
* deletion ok (*err=0), NULL device returned.
*/
*err = 0;
return NULL;
}
/*
* dev_get() with added alias naming magic.
*/
struct device *
net_alias_dev_get(char *dev_name, int aliasing_ok, int *err,
struct sockaddr *sa, void *data)
{
struct device *dev;
char *sptr,*eptr;
int slot = 0;
int delete = 0;
*err = -ENODEV;
if ((dev=dev_get(dev_name)))
return dev;
/*
* want alias naming magic?
*/
if (!aliasing_ok) return NULL;
if (!dev_name || !*dev_name)
return NULL;
/*
* find the first ':' , must be followed by, at least, 1 char
*/
for (sptr=dev_name ; *sptr ; sptr++) if(*sptr==':') break;
if (!*sptr || !*(sptr+1))
return NULL;
/*
* seems to be an alias name, fetch main device
*/
*sptr='\0';
if (!(dev=dev_get(dev_name)))
return NULL;
*sptr++=':';
/*
* fetch slot number
*/
slot = simple_strtoul(sptr,&eptr,10);
if (slot >= NET_ALIAS_MAX_SLOT)
return NULL;
/*
* if last char is '-', it is a deletion request
*/
if (eptr[0] == '-' && !eptr[1] ) delete++;
else if (eptr[0])
return NULL;
/*
* well... let's work.
*/
if (delete)
return net_alias_dev_delete(dev, slot, err);
else
return net_alias_dev_create(dev, slot, err, sa, data);
}
/*
* rehash alias with address supplied.
*/
int
net_alias_rehash(struct net_alias *alias, struct sockaddr *sa)
{
struct net_alias_info *alias_info;
struct net_alias **aliasp;
struct device *dev;
unsigned long flags;
struct net_alias_type *o_nat, *n_nat;
unsigned n_hash;
/*
* defensive ...
*/
if (!sa)
{
printk("ERROR: net_alias_rehash(): NULL sockaddr passed\n");
return -1;
}
/*
* defensive. should not happen.
*/
if (!(dev = alias->main_dev))
{
printk("ERROR: net_alias_rehash for %s: NULL maindev\n", alias->name);
return -1;
}
/*
* defensive. should not happen.
*/
if (!(alias_info=dev->alias_info))
{
printk("ERROR: net_alias_rehash for %s: NULL alias_info\n", alias->name);
return -1;
}
/*
* will the request also change device family?
*/
o_nat = alias->nat;
if (!o_nat)
{
printk("ERROR: net_alias_rehash(%s): unbound alias.\n", alias->name);
return -1;
}
/*
* point to new alias_type obj.
*/
if (o_nat->type == sa->sa_family)
n_nat = o_nat;
else
{
n_nat = nat_getbytype(sa->sa_family);
if (!n_nat)
{
printk("ERROR: net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family);
return -1;
}
}
/*
* new hash key. if same as old AND same type (family) return;
*/
n_hash = nat_hash_key(n_nat, sa);
if (n_hash == alias->hash && o_nat == n_nat )
return 0;
/*
* find alias in hashed list
*/
for (aliasp = &alias_info->hash_tab[alias->hash]; *aliasp; aliasp = &(*aliasp)->next)
if (*aliasp == alias) break;
/*
* not found (???). try a full search
*/
if(!*aliasp)
if ((aliasp = net_alias_slow_findp(alias_info, alias)))
printk("net_alias_rehash(%s): bad hashing recovered\n", alias->name);
else
{
printk("ERROR: net_alias_rehash(%s): unhashed alias!\n", alias->name);
return -1;
}
save_flags(flags);
cli();
/*
* if type (family) changed unlink from old type object (o_nat)
* will call o_nat->alias_done_1()
*/
if (o_nat != n_nat)
nat_unbind(o_nat, alias);
/*
* if diff hash key, change alias position in hashed list
*/
if (n_hash != alias->hash)
{
*aliasp = (*aliasp)->next;
alias->hash = n_hash;
aliasp = &alias_info->hash_tab[n_hash];
alias->next = *aliasp;
*aliasp = alias;
}
/*
* if type (family) changed link to new type object (n_nat)
* will call n_nat->alias_init_1()
*/
if (o_nat != n_nat)
nat_bind(n_nat, alias, sa);
restore_flags(flags);
return 0;
}
/*
* free all main device aliasing stuff
* will be called on dev_close(main_dev)
*/
static void
net_alias_free(struct device *main_dev)
{
struct net_alias_info *alias_info;
struct net_alias *alias;
struct net_alias_type *nat;
struct device *dev;
unsigned long flags;
/*
* do I really have aliases?
*/
if (!(alias_info = main_dev->alias_info)) return;
/*
* fast device link "short-circuit": set main_dev->next to
* device after last alias
*/
save_flags(flags);
cli();
dev = main_dev->next;
main_dev->next = alias_info->taildev->next;
main_dev->alias_info = NULL;
alias_info->taildev->next = NULL;
restore_flags(flags);
/*
* loop over alias devices, free and dev_close()
*/
while (dev)
{
if (net_alias_is(dev))
{
alias = dev->my_alias;
if (alias->main_dev == main_dev)
{
/*
* unbind alias from alias_type object
*/
nat = alias->nat;
if (nat)
{
nat_unbind(nat, alias);
} /* else error/printk ??? */
dev_close(dev);
dev = dev->next;
kfree_s(alias, sizeof(struct net_alias));
continue;
}
else
printk("net_alias_free(%s): '%s' is not my alias\n",
main_dev->name, alias->name);
}
else
printk("net_alias_free(%s): found a non-alias after device!\n",
main_dev->name);
dev = dev->next;
}
kfree_s(alias_info, sizeof(alias_info));
return;
}
/*
* implements /proc/net/alias_types entry
* shows net_alias_type objects registered.
*/
int net_alias_types_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
{
off_t pos=0, begin=0;
int len=0;
struct net_alias_type *nat;
unsigned idx;
len=sprintf(buffer,"type name n_attach\n");
for (idx=0 ; idx < 16 ; idx++)
for (nat = nat_base[idx]; nat ; nat = nat->next)
{
len += sprintf(buffer+len, "%-7d %-15s %-7d\n",
nat->type, nat->name,nat->n_attach);
pos=begin+len;
if(pos<offset)
{
len=0;
begin=pos;
}
if(pos>offset+length)
break;
}
*start=buffer+(offset-begin);
len-=(offset-begin);
if(len>length)
len=length;
return len;
}
/*
* implements /proc/net/aliases entry, shows alias devices.
* calls alias nat->alias_print_1 if not NULL and formats everything
* to a fixed rec. size without using local (stack) buffers
*
*/
#define NAT_REC_SIZE 64
int net_alias_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
{
off_t pos=0, begin=0;
int len=0;
int dlen;
struct net_alias_type *nat;
struct net_alias *alias;
struct device *dev;
len=sprintf(buffer,"%-*s\n",NAT_REC_SIZE-1,"device family address");
for (dev = dev_base; dev ; dev = dev->next)
if (net_alias_is(dev))
{
alias = dev->my_alias;
nat = alias->nat;
dlen=sprintf(buffer+len, "%-16s %-6d ", alias->name, alias->dev.family);
/*
* call alias_type specific print function.
*/
if (nat->alias_print_1)
dlen += nat->alias_print_1(buffer+len+dlen, NAT_REC_SIZE - dlen, alias);
else
dlen += sprintf(buffer+len+dlen, "-");
/*
* fill with spaces if needed
*/
if (dlen < NAT_REC_SIZE) memset(buffer+len+dlen, ' ', NAT_REC_SIZE - dlen);
/*
* truncate to NAT_REC_SIZE
*/
len += NAT_REC_SIZE;
buffer[len-1] = '\n';
pos=begin+len;
if(pos<offset)
{
len=0;
begin=pos;
}
if(pos>offset+length)
break;
}
*start=buffer+(offset-begin);
len-=(offset-begin);
if(len>length)
len=length;
return len;
}
/*
* notifier for devices events
*/
int net_alias_device_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct device *dev = ptr;
if (event == NETDEV_DOWN)
{
#ifdef ALIAS_USER_LAND_DEBUG
printk("net_alias: NETDEV_DOWN for %s received\n", dev->name);
#endif
if (net_alias_has(dev))
net_alias_free(dev);
}
if (event == NETDEV_UP)
{
#ifdef ALIAS_USER_LAND_DEBUG
printk("net_alias: NETDEV_UP for %s received\n", dev->name);
#endif
dev->alias_info = 0;
}
return NOTIFY_DONE;
}
/*
* returns alias device with specified address AND flags_1 on AND flags_0 off.
* intended for main devices.
* typically called on xxx_rcv() to check if packet's dest address is one
* of main_dev's alias address.
*/
struct device *
net_alias_chk(struct device *dev, struct sockaddr *sa,int flags_1, int flags_0)
{
struct net_alias_info *alias_info = dev->alias_info;
struct net_alias_type *nat;
struct net_alias *alias;
if (!alias_info) return NULL; /* has aliases? */
/*
* get alias_type object for sa->sa_family.
*/
nat = nat_getbytype(sa->sa_family);
if (!nat)
return 0;
for(alias = alias_info->hash_tab[nat_hash_key(nat,sa)];
alias; alias = alias->next)
{
if (alias->dev.family != sa->sa_family) continue;
/*
* nat_addr_chk will call type specific address cmp function.
*/
if (alias->dev.flags & flags_1 && !(alias->dev.flags & flags_0) &&
nat_addr_chk(nat,&alias->dev,sa))
return &alias->dev;
}
return NULL;
}
/*
* addr_chk enough for protocols whose addr is (fully) stored at pa_addr.
*/
struct device *
net_alias_chk32(struct device *dev, int family, __u32 addr32,
int flags_1, int flags_0)
{
struct net_alias_info *alias_info = dev->alias_info;
struct net_alias *alias;
if (!alias_info) return NULL; /* has aliases? */
for (alias=alias_info->hash_tab[HASH(addr32,family)];
alias; alias=alias->next)
{
if (alias->dev.family != family) continue;
/*
* "hard" (static) comparison between addr32 and pa_addr.
*/
if (alias->dev.flags & flags_1 && !(alias->dev.flags & flags_0) &&
addr32 == alias->dev.pa_addr)
return &alias->dev;
}
return NULL;
}
/*
* device event hook
*/
static struct notifier_block net_alias_dev_notifier = {
net_alias_device_event,
NULL,
0
};
/*
* net_alias initialisation
* called from net_dev_init().
*/
void net_alias_init(void)
{
/*
* register dev events notifier
*/
register_netdevice_notifier(&net_alias_dev_notifier);
/*
* register /proc/net entries
*/
#ifndef ALIAS_USER_LAND_DEBUG
proc_net_register(&(struct proc_dir_entry) {
PROC_NET_ALIAS_TYPES, 11, "alias_types",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
net_alias_types_getinfo
});
proc_net_register(&(struct proc_dir_entry) {
PROC_NET_ALIASES, 7, "aliases",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_net_inode_operations,
net_alias_getinfo
});
#endif
}
/*
* net_alias type object registering func.
*/
int register_net_alias_type(struct net_alias_type *nat, int type)
{
unsigned hash;
unsigned long flags;
if (!nat)
{
printk("register_net_alias_type(): NULL arg\n");
return -EINVAL;
}
nat->type = type;
nat->n_attach = 0;
hash = nat->type & 0x0f;
save_flags(flags);
cli();
nat->next = nat_base[hash];
nat_base[hash] = nat;
restore_flags(flags);
return 0;
}
/*
* net_alias type object unreg.
*/
int unregister_net_alias_type(struct net_alias_type *nat)
{
struct net_alias_type **natp;
unsigned hash;
unsigned long flags;
if (!nat)
{
printk("unregister_net_alias_type(): NULL arg\n");
return -EINVAL;
}
/*
* only allow unregistration if it has no attachments
*/
if (nat->n_attach)
{
printk("unregister_net_alias_type(): has %d attachments. failed\n",
nat->n_attach);
return -EINVAL;
}
hash = nat->type & 0x0f;
save_flags(flags);
cli();
for (natp = &nat_base[hash]; *natp ; natp = &(*natp)->next)
{
if (nat==(*natp))
{
*natp = nat->next;
restore_flags(flags);
return 0;
}
}
restore_flags(flags);
printk("unregister_net_alias_type(type=%d): not found!\n", nat->type);
return -EINVAL;
}
......@@ -17,6 +17,9 @@ if [ "$CONFIG_IP_FORWARD" = "y" ]; then
bool 'IP: multicast routing(in progress)' CONFIG_IP_MROUTE
fi
fi
if [ "$CONFIG_NET_ALIAS" = "y" ]; then
tristate 'IP: aliasing support' CONFIG_IP_ALIAS
fi
comment '(it is safe to leave these untouched)'
bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP
tristate 'IP: Reverse ARP' CONFIG_INET_RARP
......
......@@ -36,6 +36,14 @@ else
endif
endif
ifeq ($(CONFIG_IP_ALIAS),y)
IPV4_OBJS += ip_alias.o
else
ifeq ($(CONFIG_IP_ALIAS),m)
M_OBJS += ip_alias.o
endif
endif
ifdef CONFIG_INET
O_OBJS := $(IPV4_OBJS)
endif
......
......@@ -88,6 +88,9 @@
#include <net/raw.h>
#include <net/icmp.h>
#include <linux/ip_fw.h>
#ifdef CONFIG_IP_ALIAS
#include <net/ip_alias.h>
#endif
#define min(a,b) ((a)<(b)?(a):(b))
......@@ -1530,6 +1533,13 @@ void inet_proto_init(struct net_proto *pro)
ip_mr_init();
#endif
/*
* Initialise AF_INET alias type (register net_alias_type)
*/
#if defined(CONFIG_IP_ALIAS)
ip_alias_init();
#endif
/*
* Create all the /proc entries.
*/
......
......@@ -96,6 +96,9 @@
#include <net/netrom.h>
#endif
#endif
#ifdef CONFIG_NET_ALIAS
#include <linux/net_alias.h>
#endif
#include <asm/system.h>
#include <asm/segment.h>
......@@ -891,6 +894,19 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* cache.
*/
/*
* try to switch to alias device whose address is tip, if any
*/
#ifdef CONFIG_NET_ALIAS
if (net_alias_has(dev))
{
struct device *adev;
adev = net_alias_chk32(dev,AF_INET,tip,IFF_UP,IFF_NOARP);
if (adev != NULL) dev = adev;
}
#endif
if (arp->ar_op == htons(ARPOP_REQUEST))
{
/*
......@@ -1019,7 +1035,15 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
entry->timer.data = (unsigned long)entry;
memcpy(entry->ha, sha, dev->addr_len);
entry->last_updated = entry->last_used = jiffies;
/*
* make entry point to 'correct' device
*/
#ifdef CONFIG_NET_ALIAS
entry->dev = dev;
#else
entry->dev = skb->dev;
#endif
skb_queue_head_init(&entry->skb);
if (arp_lock == 1)
{
......
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/if.h>
#include <linux/inet.h>
#ifdef ALIAS_USER_LAND_DEBUG
#include "net_alias.h"
#include "ip_alias.h"
#include "user_stubs.h"
#endif
#include <linux/net_alias.h>
#include <net/ip_alias.h>
/*
* AF_INET alias init
*/
static int
ip_alias_init_1(struct net_alias *alias, struct sockaddr *sa)
{
#ifdef ALIAS_USER_LAND_DEBUG
printk("alias_init(%s) called.\n", alias->name);
#endif
MOD_INC_USE_COUNT;
return 0;
}
/*
* AF_INET alias done
*/
static int
ip_alias_done_1(struct net_alias *alias)
{
#ifdef ALIAS_USER_LAND_DEBUG
printk("alias_done(%s) called.\n", alias->name);
#endif
MOD_DEC_USE_COUNT;
return 0;
}
/*
* print address info
*/
int
ip_alias_print_1(char *buf, int len, struct net_alias *alias)
{
char *p;
p = (char *) &alias->dev.pa_addr;
return sprintf(buf, "%d.%d.%d.%d",
(p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
}
/*
* net_alias AF_INET type defn.
*/
struct net_alias_type ip_alias_type =
{
AF_INET, /* type */
0, /* n_attach */
"ip", /* name */
NULL, /* get_addr32() */
NULL, /* addr_chk() */
ip_alias_init_1, /* alias_init_1() */
ip_alias_done_1, /* alias_done_1() */
ip_alias_print_1, /* alias_print_1() */
NULL /* next */
};
/*
* ip_alias module initialization
*/
int ip_alias_init(void)
{
return register_net_alias_type(&ip_alias_type, AF_INET);
}
/*
* ip_alias module done
*/
int ip_alias_done(void)
{
return unregister_net_alias_type(&ip_alias_type);
}
#ifdef MODULE
int init_module(void)
{
if (ip_alias_init() != 0)
return -EIO;
return 0;
}
void cleanup_module(void)
{
if (ip_alias_done() != 0)
printk("ip_alias: can't remove module");
}
#endif /* MODULE */
......@@ -151,6 +151,9 @@
#include <linux/firewall.h>
#include <linux/mroute.h>
#include <net/netlink.h>
#ifdef CONFIG_NET_ALIAS
#include <linux/net_alias.h>
#endif
extern int last_retran;
extern void sort_send(struct sock *sk);
......@@ -313,7 +316,18 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* function entry.
*/
/*
* also check device aliases address : will avoid
* a full lookup over device chain
*/
#ifdef CONFIG_NET_ALIAS
if ( iph->daddr == skb->dev->pa_addr ||
( net_alias_has(skb->dev) && net_alias_addr_chk32(skb->dev,AF_INET, iph->daddr )) ||
(brd = ip_chk_addr(iph->daddr)) != 0)
#else
if ( iph->daddr == skb->dev->pa_addr || (brd = ip_chk_addr(iph->daddr)) != 0)
#endif
{
if (opt && opt->srr)
{
......
......@@ -20,6 +20,8 @@
# 180995 Bernhard Kaindl (bkaindl@ping.at) - added dummy functions for
# use with a config.in modified for make menuconfig.
#
# 301195 (boldt@math.ucsb.edu) - added help text support
#
#
# Make sure we're really running bash.
......@@ -44,6 +46,37 @@ function mainmenu_name () {
:
}
#
# help prints the corresponding help text from Configure.help to stdout
#
# help variable
#
function help () {
if [ -f Documentation/Configure.help ]
then
#first escape regexp special characters in the argument:
var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
#now pick out the right help text:
text=$(sed -n "/^$var[ ]*\$/,\${
/^$var[ ]*\$/b
/^#.*/b;/^[ ]*\$/q
p
}" Documentation/Configure.help)
if [ -z "$text" ]
then
echo; echo " Sorry, no help available for this option yet.";echo
else
(echo; echo "$text"; echo) | more
fi
else
echo;
echo " Can't access the file Documentation/Configure.help which"
echo " should contain the help texts."
echo
fi
}
#
# readln reads a line into $ans.
#
......@@ -78,17 +111,17 @@ function comment () {
#
function define_bool () {
case "$2" in
"y" | "Y")
"y")
echo "$1=y" >>$CONFIG
echo "#define $1 1" >>$CONFIG_H
;;
"m" | "M")
"m")
echo "$1=m" >>$CONFIG
echo "#undef $1" >>$CONFIG_H
;;
"n" | "N")
"n")
echo "# $1 is not set" >>$CONFIG
echo "#undef $1" >>$CONFIG_H
;;
......@@ -102,18 +135,24 @@ function define_bool () {
# bool question define
#
function bool () {
ans=""
def=$(eval echo "\${$2:-'n'}")
case "$def" in
"y") defprompt="Y/n"
"y") defprompt="Y/n/?"
;;
"n") defprompt="N/y"
"n") defprompt="N/y/?"
;;
esac
while [ "$ans" != "y" -a "$ans" != "n" ]; do
readln "$1 ($2) [$defprompt] " "$def"
done
define_bool "$2" "$ans"
while :; do
readln "$1 ($2) [$defprompt] " "$def"
case "$ans" in
[yY] | [yY]es ) define_bool "$2" "y"
break;;
[nN] | [nN]o ) define_bool "$2" "n"
break;;
* ) help "$2"
;;
esac
done
}
#
......@@ -122,20 +161,28 @@ function bool () {
# tristate question define
#
function tristate () {
ans=""
def=$(eval echo "\${$2:-'n'}")
case "$def" in
"y") defprompt="Y/m/n"
"y") defprompt="Y/m/n/?"
;;
"m") defprompt="M/n/y"
"m") defprompt="M/n/y/?"
;;
"n") defprompt="N/y/m"
"n") defprompt="N/y/m/?"
;;
esac
while [ "$ans" != "y" -a "$ans" != "n" -a "$ans" != "m" ]; do
readln "$1 ($2) [$defprompt] " "$def"
done
define_bool "$2" "$ans"
while :; do
readln "$1 ($2) [$defprompt] " "$def"
case "$ans" in
[yY] | [yY]es ) define_bool "$2" "y"
break ;;
[nN] | [nN]o ) define_bool "$2" "n"
break ;;
[mM] ) define_bool "$2" "m"
break ;;
* ) help "$2"
;;
esac
done
}
#
......@@ -153,18 +200,32 @@ function dep_tristate () {
if [ "$3" != "m" ]; then
tristate "$1" "$2"
else
ans=""
case "$def" in
"y" | "m") defprompt="M/n"
"y" | "m") defprompt="M/n/?"
def="m"
;;
"n") defprompt="N/m"
"n") defprompt="N/m/?"
;;
esac
while [ "$ans" != "n" -a "$ans" != "m" ]; do
readln "$1 ($2) [$defprompt] " "$def"
done
define_bool "$2" "$ans"
while :; do
readln "$1 ($2) [$defprompt] " "$def"
case "$ans" in
[nN] | [nN]o ) define_bool "$2" "n"
break ;;
[mM] ) define_bool "$2" "m"
break ;;
[yY] | [yY]es ) echo
echo " This answer is not allowed, because it is not consistent with"
echo " your other choices."
echo " This driver depends on another one which you chose to compile"
echo " as a module. This means that you can either compile this one"
echo " as a module as well (with M) or leave it out altogether (N)."
echo
;;
* ) help "$2"
;;
esac
done
fi
}
......@@ -185,13 +246,17 @@ function define_int () {
# int question define default
#
function int () {
# Slimier hack to get bash to rescan a line.
ans="x"
def=$(eval echo "\${$2:-$3}")
while [ $[$ans+0] != "$ans" ]; do
readln "$1 ($2) [$def] " "$def"
done
define_int "$2" "$ans"
while :; do
readln "$1 ($2) [$def] " "$def"
case "$ans" in
[1-9] | [1-9][0-9] | [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] )
define_int "$2" "$ans"
break;;
* ) help "$2"
;;
esac
done
}
#
......@@ -216,6 +281,7 @@ function choice () {
# determine default answer:
names=""
set -- $choices
firstvar=$2
while [ -n "$2" ]; do
if [ -n "$names" ]; then
names="$names, $1"
......@@ -230,29 +296,34 @@ function choice () {
val=""
while [ -z "$val" ]; do
ambg=n
readln "$question ($names) [$def] " "$def"
ans=$(echo $ans | tr a-z A-Z)
set -- $choices
val=""
while [ -n "$1" ]; do
name=$(echo $1 | tr a-z A-Z)
case "$name" in
${ans}*)
"$ans"* )
if [ "$name" = "$ans" ]; then
val="$2"
break # stop on exact match
fi
if [ -n "$val" ]; then
echo \
echo;echo \
" Sorry, \"$ans\" is ambiguous; please enter a longer string."
echo
val=""
ambg=y
break
else
val="$2"
fi;;
esac
shift; shift
done
done
if [ "$val" = "" -a "$ambg" = "n" ]; then
help "$firstvar"
fi
done
set -- $choices
while [ -n "$2" ]; do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment