]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.128pre1 2.1.128pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:17:12 +0000 (15:17 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:17:12 +0000 (15:17 -0500)
111 files changed:
CREDITS
Documentation/Configure.help
Documentation/mca.txt
Documentation/sysctl/kernel.txt
Documentation/video4linux/bttv/INSTALL
MAINTAINERS
Makefile
arch/i386/kernel/time.c
arch/i386/kernel/traps.c
arch/m68k/atari/stram.c
arch/m68k/config.in
arch/m68k/kernel/m68k_defs.h
arch/m68k/kernel/process.c
arch/m68k/kernel/ptrace.c
arch/mips/kernel/irixelf.c
arch/sparc64/kernel/binfmt_aout32.c
drivers/block/acsi.c
drivers/block/floppy.c
drivers/block/ps2esdi.c
drivers/block/xd.c
drivers/cdrom/mcdx.c
drivers/char/bttv.c
drivers/char/bttv.h
drivers/char/ftape/lowlevel/fdc-io.c
drivers/char/ftape/zftape/zftape-buffers.c
drivers/char/pms.c
drivers/char/saa5249.c
drivers/char/tuner.c
drivers/char/tuner.h
drivers/char/videodev.c
drivers/net/3c515.c [new file with mode: 0644]
drivers/net/3c523.c
drivers/net/3c59x.c
drivers/net/Config.in
drivers/net/Makefile
drivers/net/Space.c
drivers/net/ariadne2.c
drivers/net/at1700.c
drivers/net/ibmtr.c
drivers/net/ipddp.c
drivers/net/rtl8139.c
drivers/net/strip.c
drivers/net/yellowfin.c
drivers/net/z85230.c
drivers/pci/pcisyms.c
drivers/scsi/Config.in
drivers/scsi/Makefile
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx/sequencer.h
drivers/scsi/blz1230.c
drivers/scsi/blz2060.c
drivers/scsi/cyberstorm.c
drivers/scsi/fastlane.c
drivers/scsi/fd_mcs.c [new file with mode: 0644]
drivers/scsi/fd_mcs.h [new file with mode: 0644]
drivers/scsi/hosts.c
drivers/scsi/scsicam.c
drivers/sound/Readme.modules
drivers/sound/ad1848.c
drivers/sound/audio.c
drivers/sound/dev_table.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/dmasound.c
drivers/sound/mad16.c
drivers/sound/os.h
drivers/sound/sb.h
drivers/sound/sb_audio.c
drivers/sound/sb_common.c
drivers/sound/sb_mixer.h
drivers/sound/sgalaxy.c
drivers/sound/soundcard.c
drivers/sound/wavfront.c
drivers/sound/wf_midi.c
fs/binfmt_aout.c
fs/exec.c
fs/ext2/dir.c
fs/lockd/svc.c
fs/lockd/svclock.c
fs/minix/dir.c
fs/nfs/write.c
fs/open.c
fs/proc/array.c
fs/proc/root.c
fs/super.c
fs/sysv/dir.c
fs/ufs/dir.c
include/asm-alpha/spinlock.h
include/asm-i386/dma.h
include/asm-i386/shmparam.h
include/asm-m68k/ide.h
include/asm-m68k/serial.h
include/linux/acct.h
include/linux/fs.h
include/linux/kernel.h
include/linux/nfs_fs.h
include/linux/sched.h
include/linux/sysctl.h
include/linux/zorro.h
init/main.c
kernel/acct.c
kernel/sysctl.c
lib/vsprintf.c
mm/filemap.c
mm/vmscan.c
net/802/fddi.c
net/econet/econet.c
net/socket.c
net/wanrouter/wanproc.c
scripts/lxdialog/menubox.c
scripts/lxdialog/textbox.c

diff --git a/CREDITS b/CREDITS
index 8129e570785917b57e196ae2c5deda20d60b7216..29eac8681b96cea7eaf71ea449a41fb9ffb35943 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1677,11 +1677,12 @@ S: Cliffwood, New Jersey 07721
 S: USA
 
 N: Henrik Storner
-E: storner@osiris.ping.dk
-E: storner@olicom.dk
-W: http://eolicom.olicom.dk/~storner/
-D: Configure script: tristate, bugfixes
+E: storner@image.dk
+W: http://www.image.dk/~storner/
+W: http://www.sslug.dk/
+D: Configure script: Invented tristate for module-configuration
 D: vfat/msdos integration, kerneld docs, Linux promotion
+D: Miscellaneous bug-fixes
 S: Chr. Winthersvej 1 B, st.th.
 S: DK-1860 Frederiksberg C
 S: Denmark
@@ -1911,6 +1912,11 @@ N: Juergen Weigert
 E: jnweiger@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
+N: David Weinehall
+E: tao@acc.umu.se
+D: NE/2-driver maintainer
+D: Miscellaneous MCA-support
+
 N: Matt Welsh
 E: mdw@sunsite.unc.edu
 D: Linux Documentation Project coordinator
index ad33d316147823346bd1565798fae210f36b6c10..c449ef5b3bedca0cf0c0fe832fb142458f2f07bb 100644 (file)
@@ -78,7 +78,7 @@ CONFIG_EXPERIMENTAL
   with the kernel internals are usually welcomed by the developers
   (before submitting bug reports, please read the documents README,
   MAINTAINERS, Documentation/BUG-HUNTING, and
-  Documentation/oops-tracing.txt in the kernel source).  
+  Documentation/oops-tracing.txt in the kernel source). 
 
   Unless you intend to help test and develop a feature or driver that
   falls into this category, or you have a situation that requires
@@ -92,7 +92,7 @@ CONFIG_MATH_EMULATION
   Linux can emulate a math coprocessor (used for floating point
   operations) if you don't have one. 486DX and Pentium processors have
   a math coprocessor built in, 486SX and 386 do not, unless you added
-  a 487DX or 387, respectively.  (The messages during boot time can
+  a 487DX or 387, respectively. (The messages during boot time can
   give you some hints here ["man dmesg"].) Everyone needs either a
   coprocessor or this emulation. 
 
@@ -110,7 +110,7 @@ CONFIG_MATH_EMULATION
   math coprocessor emulation can be found in
   arch/i386/math-emu/README.
 
-  If you are not sure, say Y; apart from resulting in a 45kB bigger
+  If you are not sure, say Y; apart from resulting in a 45 KB bigger
   kernel, it won't hurt.
 
 Normal PC floppy disk support
@@ -127,16 +127,22 @@ CONFIG_BLK_DEV_FD
   The module will be called floppy.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+Support for PowerMac floppy
+CONFIG_MAC_FLOPPY
+  If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
+  floppy controller, say Y here. Most commonly found in PowerMacs.
+
 RAM disk support
 CONFIG_BLK_DEV_RAM
   Saying Y here will allow you to use a portion of your RAM memory as
   a block device, so that you can make filesystems on it, read and
   write to it and do all the other things that you can do with normal
-  block devices (such as hard drives).  It is usually used to load and
+  block devices (such as hard drives). It is usually used to load and
   store a copy of a minimal root file system off of a floppy into RAM
-  during the initial install of Linux.  Note that the kernel command
-  line option "ramdisk=XX" is now obsolete.  For details, read
-  Documentation/ramdisk.txt. 
+  during the initial install of Linux. 
+
+  Note that the kernel command line option "ramdisk=XX" is now
+  obsolete. For details, read Documentation/ramdisk.txt.
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -158,8 +164,8 @@ Loop device support
 CONFIG_BLK_DEV_LOOP
   Saying Y here will allow you to use a regular file as a block
   device; you can then create a file system on that block device and
-  mount it just as you would mount other block devices such as hard drive
-  partitions, CDROM drives or floppy drives.
+  mount it just as you would mount other block devices such as hard
+  drive partitions, CDROM drives or floppy drives.
 
   This is useful if you want to check an ISO 9660 file system before
   burning the CD, or if you want to use floppy images without first
@@ -171,8 +177,9 @@ CONFIG_BLK_DEV_LOOP
   bits of, say, a sound file). This is also safe if the file resides
   on a remote file server. If you want to do this, you will first have
   to acquire and install a kernel patch from
-  ftp://ftp.replay.com/pub/crypto/linux/all, and then you need to say
-  Y to this option.
+  ftp://ftp.replay.com/pub/crypto/linux/all or
+  ftp://verden.pvv.org/pub/linux/kerneli/v2.1/, and then you need to
+  say Y to this option.
 
   Note that alternative ways to use encrypted filesystems are provided
   by the cfs package, which can be gotten via FTP (user: anonymous)
@@ -200,18 +207,22 @@ CONFIG_BLK_DEV_LOOP
 Network Block Device support
 CONFIG_BLK_DEV_NBD
   Saying Y here will allow your computer to be a client for network
-  block devices -- it will be able to use block devices exported by
+  block devices, i.e. it will be able to use block devices exported by
   servers (mount filesystems on them etc.). Communication between
   client and server works over TCP/IP networking, but to the client
   program this is hidden: it looks like a regular local file access to
-  a special file such as /dev/nd0. It also allows you to run a
-  block-device in userland (making server and client physically the
-  same computer, communicating using the loopback network device).
+  a block device special file such as /dev/nd0. 
+
+  Network block devices also allows you to run a block-device in
+  userland (making server and client physically the same computer,
+  communicating using the loopback network device).
+  
   Read Documentation/nbd.txt for more information, especially about
-  where to find the server code.
+  where to find the server code, which runs in user space and does not
+  need special kernel support.
 
-  Note that this has nothing to do with the network file system NFS;
-  you can say N here even if you intend to use NFS.
+  Note that this has nothing to do with the network file systems NFS
+  or Coda; you can say N here even if you intend to use NFS or Coda.
 
   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),
@@ -225,22 +236,25 @@ CONFIG_BLK_DEV_IDE
   If you say Y here, you will use the full-featured IDE driver to
   control up to four IDE interfaces, each being able to serve a
   "master" and a "slave" device, for a total of up to eight IDE
-  disk/cdrom/tape/floppy drives.  People with SCSI-only systems
-  should say 'N' here.
-
-  Useful information about large (>540MB) IDE disks, sound card IDE
-  ports, module support, and other topics, is contained in
-  Documentation/ide.txt. For detailed information about hard drives,
-  consult the Disk-HOWTO, available via FTP (user: anonymous) from
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. To fine-tune IDE
-  drive/interface parameters for improved performance, look for the
-  hdparm package at
-  sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/
+  disk/cdrom/tape/floppy drives. People with SCSI-only systems
+  can say N here.
+
+  Useful information about large (>540 MB) IDE disks, multiple
+  interfaces, what to do if IDE devices are not automatically
+  detected, sound card IDE ports, module support, and other topics, is
+  contained in Documentation/ide.txt. For detailed information about
+  hard drives, consult the Disk-HOWTO and the Multi-Disk-HOWTO,
+  available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
+
+  To fine-tune IDE drive/interface parameters for improved
+  performance, look for the hdparm package at
+  ftp://sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/
 
   If you have one or more IDE drives, say Y here. If your system has
   no IDE drives, or if memory requirements are really tight, you could
   say N here, and select the "Old hard disk driver" instead to save
-  about 13kB of memory in the kernel.
+  about 13 KB of memory in the kernel.
 
 Old hard disk (MFM/RLL/IDE) driver
 CONFIG_BLK_DEV_HD_ONLY
@@ -252,12 +266,14 @@ CONFIG_BLK_DEV_HD_ONLY
   since it lacks the enhanced functionality of the new one. This makes
   it a good choice for systems with very tight memory restrictions, or
   for systems with only older MFM/RLL/ESDI drives. Choosing the old
-  driver can save 13kB or so of kernel memory. If you are unsure, then
-  just choose the Enhanced IDE/MFM/RLL driver instead of this one. For
-  more detailed information, read the Disk-HOWTO, available via FTP
-  (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+  driver can save 13 KB or so of kernel memory. 
 
-  People with SCSI-only systems can say 'N' here.
+  If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
+  instead of this one. For more detailed information, read the
+  Disk-HOWTO, available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+  People with SCSI-only systems can say N here.
 
 Use old disk-only driver on primary interface
 CONFIG_BLK_DEV_HD_IDE
@@ -270,16 +286,20 @@ CONFIG_BLK_DEV_HD_IDE
   interface. Choosing this option may be useful for older systems
   which have MFM/RLL/ESDI controller+drives at the primary port
   address (0x1f0), along with IDE drives at the secondary/3rd/4th port
-  addresses. Normally, just say N here; you will then use the new
-  driver for all 4 interfaces.
+  addresses. 
+
+  Normally, just say N here; you will then use the new driver for all
+  4 interfaces.
 
-  People with SCSI-only systems can say 'N' here.
+  People with SCSI-only systems don't need this and can say N here as
+  well.
 
 Include IDE/ATA-2 DISK support
 CONFIG_BLK_DEV_IDEDISK
-  This will include enhanced support for MFM/RLL/IDE hard disks. If you
-  have a MFM/RLL/IDE disk, and there is no special reason to use the
-  old hard disk driver instead, say Y.  If all your disks are SCSI, say 'N'.
+  This will include enhanced support for MFM/RLL/IDE hard disks. If
+  you have a MFM/RLL/IDE disk, and there is no special reason to use
+  the old hard disk driver instead, say Y. If you have an SCSI-only
+  system, you can say N here.
 
   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),
@@ -318,7 +338,8 @@ Include IDE/ATAPI TAPE support
 CONFIG_BLK_DEV_IDETAPE
   If you have an IDE tape drive using the ATAPI protocol, say Y.
   ATAPI is a newer protocol used by IDE tape and CDROM drives, similar
-  to the SCSI protocol (but say 'N' if your tape is a SCSI device).
+  to the SCSI protocol. If you have an SCSI tape drive however, you
+  can say N here.
 
   If you say Y here, the tape drive will be identified at boot time
   along with other IDE devices, as "hdb" or "hdc", or something
@@ -334,12 +355,12 @@ CONFIG_BLK_DEV_IDETAPE
 
 Include IDE/ATAPI FLOPPY support
 CONFIG_BLK_DEV_IDEFLOPPY
-  If you have an IDE floppy drive which uses the ATAPI protocol, say
-  Y.  ATAPI is a newer protocol used by IDE CDROM/tape/floppy drives,
-  similar to the SCSI protocol.  IDE floppy drives include the LS-120
-  and the ATAPI ZIP (ATAPI PD-CD/CDR drives are not supported by this
-  driver; support for PD-CD/CDR drives is available if you say Y to
-  "SCSI emulation support", below).
+  If you have an IDE floppy drive which uses the ATAPI protocol,
+  answer Y. ATAPI is a newer protocol used by IDE CDROM/tape/floppy
+  drives, similar to the SCSI protocol. IDE floppy drives include the
+  LS-120 and the ATAPI ZIP (ATAPI PD-CD/CDR drives are not supported
+  by this driver; support for PD-CD/CDR drives is available if you
+  answer Y to "SCSI emulation support", below).
 
   If you say Y here, the FLOPPY drive will be identified along with
   other IDE devices, as "hdb" or "hdc", or something similar (check
@@ -368,18 +389,18 @@ CONFIG_BLK_DEV_IDESCSI
   If both this SCSI emulation and native ATAPI support are compiled
   into the kernel, the native support will be used.
 
-  People with SCSI-only systems should say 'N' here.  If unsure, say N.
+  People with SCSI-only systems can say N here. If unsure, say N.
 
 CMD640 chipset bugfix/support
 CONFIG_BLK_DEV_CMD640
   The CMD-Technologies CMD640 IDE chip is used on many common 486 and
   Pentium motherboards, usually in combination with a "Neptune" or
-  "SiS" chipset.  Unfortunately, it has a number of rather nasty
+  "SiS" chipset. Unfortunately, it has a number of rather nasty
   design flaws that can cause severe data corruption under many common
-  conditions.  Say Y here to include code which tries to automatically
-  detect and correct the problems under Linux.  This option also
+  conditions. Say Y here to include code which tries to automatically
+  detect and correct the problems under Linux. This option also
   enables access to the secondary IDE ports in some CMD640 based
-  systems.  
+  systems. 
 
   This driver will work automatically in PCI based systems (most new
   systems have PCI slots). But if your system uses VESA local bus
@@ -394,36 +415,35 @@ CONFIG_BLK_DEV_CMD640
   the "CSA-6400E PCI to IDE controller" that some people have. For
   details, read Documentation/ide.txt. 
 
-  People with SCSI-only systems should say 'N' here.  If unsure, say Y.
+  People with SCSI-only systems should say N here. If unsure, say Y.
 
 CMD640 enhanced support
 CONFIG_BLK_DEV_CMD640_ENHANCED
   This option includes support for setting/autotuning PIO modes and
-  prefetch on CMD640 IDE interfaces.  For details, read
+  prefetch on CMD640 IDE interfaces. For details, read
   Documentation/ide.txt. If you have a CMD640 IDE interface and your
-  BIOS does not already do this for you, then say Y here.  Otherwise
+  BIOS does not already do this for you, then say Y here. Otherwise
   say N.
 
 RZ1000 chipset bugfix/support
 CONFIG_BLK_DEV_RZ1000
-  The PC-Technologies RZ1000 chip is used on many common 486 and
+  The PC-Technologies RZ1000 IDE chip is used on many common 486 and
   Pentium motherboards, usually along with the "Neptune" chipset.
   Unfortunately, it has a rather nasty design flaw that can cause
-  severe data corruption under many conditions.  Say Y here to include
+  severe data corruption under many conditions. Say Y here to include
   code which automatically detects and corrects the problem under
-  Linux.  This may slow disk throughput by a few percent, but at least
+  Linux. This may slow disk throughput by a few percent, but at least
   things will operate 100% reliably. 
 
-  People with SCSI-only systems can say 'N' here.  If unsure, say Y.
+  People with SCSI-only systems should say N here. If unsure, say Y.
 
 Generic PCI IDE chipset support
 CONFIG_BLK_DEV_IDEPCI
   Enable this for PCI systems which use IDE drive(s).
   This option helps the IDE driver to automatically detect and
   configure all PCI-based IDE interfaces in your system.
-
-  People with SCSI-only systems should say 'N' here.   It is safe to
-  say 'Y' to this question.
+  
+  People with SCSI-only systems should say N here; if unsure say Y.
 
 Generic PCI bus-master DMA support
 CONFIG_BLK_DEV_IDEDMA
@@ -442,26 +462,33 @@ CONFIG_BLK_DEV_IDEDMA
 
   It is safe to say Y to this question.
 
+Winbond SL82c105 support
+CONFIG_BLK_DEV_SL82C105
+  If you have a Winbond SL82c105 IDE controller, say Y here to enable
+  special configuration for this chip. This is common on various CHRP
+  motherboards, but could be used elsewhere. If in doubt, say Y.
+
 Boot off-board chipsets first support
 CONFIG_BLK_DEV_OFFBOARD
   Normally, IDE controllers built into the motherboard (on-board
-  controllers) are assigned to ide0 and ide1 while those on add-in
-  PCI cards (off-board controllers) are relegated to ide2 and ide3.
-  Saying Y to here will reverse the situation, with off-board
-  controllers on ide0/1 and on-board controllers on ide2/3. This
-  can improve the usability of some boot managers such as LILO
-  when booting from a drive on an off-board controller.
-  Note that this will rearrange the order of the hd* devices and
-  may require modification of fstab and other files.
+  controllers) are assigned to ide0 and ide1 while those on add-in PCI
+  cards (off-board controllers) are relegated to ide2 and ide3.
+  Answering Y here will reverse the situation, with off-board
+  controllers on ide0/1 and on-board controllers on ide2/3. This can
+  improve the usability of some boot managers such as LILO when
+  booting from a drive on an off-board controller.
+
+  Note that, if you say Y here, the order of the hd* devices will be
+  rearranged which may require modification of fstab and other files.
 
   If in doubt, say N.
 
 Use DMA by default when available
 CONFIG_IDEDMA_AUTO
   Prior to kernel version 2.1.112, Linux used to automatically use
-  DMA for IDE drives and chipsets which support it.  Due to concerns
+  DMA for IDE drives and chipsets which support it. Due to concerns
   about a couple of cases where buggy hardware may have caused damage,
-  the default is now to NOT use DMA automatically.  To revert to the
+  the default is now to NOT use DMA automatically. To revert to the
   previous behaviour, say Y to this question.
 
   If you suspect your hardware is at all flakey, say N here.
@@ -472,46 +499,48 @@ CONFIG_IDEDMA_AUTO
 Other IDE chipset support
 CONFIG_IDE_CHIPSETS
   Say Y here if you want to include enhanced support for various IDE
-  interface chipsets used on motherboards and add-on cards.  This
-  enhanced support may be necessary for Linux to be able to access the
-  3rd/4th drives in some systems.  It may also enable setting of
-  higher speed I/O rates to improve system performance with these
-  chipsets.  Most of these also require special kernel boot parameters
-  to actually turn on the support at runtime.
-
-  People with SCSI-only systems should say 'N' here. 
+  interface chipsets used on motherboards and add-on cards. You can
+  then pick your particular IDE chip from among the following options.
+  This enhanced support may be necessary for Linux to be able to
+  access the 3rd/4th drives in some systems. It may also enable
+  setting of higher speed I/O rates to improve system performance with
+  these chipsets. Most of these also require special kernel boot
+  parameters to actually turn on the support at runtime; you can find
+  a list of these in the file Documentation/ide.txt.
+  
+  People with SCSI-only systems can say N here. 
 
 Generic 4 drives/port support
 CONFIG_BLK_DEV_4DRIVES
-  Certain older chipsets, including the Tekram 690CD, use a
-  single set of I/O ports at 0x1f0 to control up to four drives,
-  instead of the customary two drives per port.  Support for this
-  can be enabled at runtime using the "ide0=four" kernel boot
-  parameter if you say Y here.
+  Certain older chipsets, including the Tekram 690CD, use a single set
+  of I/O ports at 0x1f0 to control up to four drives, instead of the
+  customary two drives per port. Support for this can be enabled at
+  runtime using the "ide0=four" kernel boot parameter if you say Y
+  here.
 
 DTC-2278 support
 CONFIG_BLK_DEV_DTC2278
   This driver is enabled at runtime using the "ide0=dtc2278" kernel
-  boot parameter.  It enables support for the secondary IDE interface
+  boot parameter. It enables support for the secondary IDE interface
   of the DTC-2278 card, and permits faster I/O speeds to be set as
-  well.  See the Documentation/ide.txt and dtc2278.c files for more
+  well. See the Documentation/ide.txt and dtc2278.c files for more
   info.
 
 Holtek HT6560B support
 CONFIG_BLK_DEV_HT6560B
   This driver is enabled at runtime using the "ide0=ht6560b" kernel
-  boot parameter.  It enables support for the secondary IDE interface
+  boot parameter. It enables support for the secondary IDE interface
   of the Holtek card, and permits faster I/O speeds to be set as well.
   See the Documentation/ide.txt and ht6560b.c files for more info.
 
 PROMISE DC4030 support (EXPERIMENTAL)
 CONFIG_BLK_DEV_PDC4030
   This driver provides support for the secondary IDE interface and
-  cache of Promise IDE chipsets, e.g. DC4030 and DC5030.  This driver
+  cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver
   is known to incur timeouts/retries during heavy I/O to drives
-  attached to the secondary interface.  CDROM and TAPE devices are not
-  supported yet.  This driver is enabled at runtime using the
-  "ide0=dc4030" kernel boot parameter.  See the Documentation/ide.txt
+  attached to the secondary interface. CDROM and TAPE devices are not
+  supported yet. This driver is enabled at runtime using the
+  "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt
   and drivers/block/pdc4030.c files for more info.
 
 PS/2 ESDI hard disk support
@@ -522,7 +551,7 @@ CONFIG_BLK_DEV_PS2
 Tekram TRM290 chipset support (EXPERIMENTAL)
 CONFIG_BLK_DEV_TRM290
   This driver adds support for bus master DMA transfers
-  using the Tekram TRM290 PCI IDE chip.  Volunteers are
+  using the Tekram TRM290 PCI IDE chip. Volunteers are
   needed for further tweaking and development.
   Please read the comments at the top of drivers/block/trm290.c.
 
@@ -541,41 +570,47 @@ CONFIG_BLK_DEV_NS87415
 VIA82C586 chipset support (EXPERIMENTAL)
 CONFIG_BLK_DEV_VIA82C586
   This adds initial timing settings for VIA (U)DMA onboard ide
-  controllers that are ATA3 compliant.  May work with ATA4 systems,
-  but not tested to date.
+  controllers that are ATA3 compliant. May work with ATA4 systems, but
+  not tested to date.
+
+  If you say Y here, you also need to say Y to "Use DMA by default
+  when available", above.
 
-  This requires CONFIG_IDEDMA_AUTO to be enabled.
   Please read the comments at the top of drivers/block/via82C586.c
 
   If unsure, say N.
 
+CMD646 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_CMD646
+  Say Y here if you have an IDE controller like this.
+
 HPT343 chipset support (EXPERIMENTAL)
 CONFIG_BLK_DEV_HPT343
-  This driver adds up to 4 more eide devices sharing a single interrupt.
-  The HPT343 chipset in it's current form is a non-bootable PCI
-  UDMA controller.  This driver requires dynamic tuning of the
-  chipset during the ide-probe at boot.  It is reported to support
-  DVD II drives, by the manufacturer.
+  This driver adds up to 4 more EIDE devices sharing a single
+  interrupt. The HPT343 chipset in its current form is a non-bootable
+  PCI UDMA controller. This driver requires dynamic tuning of the
+  chipset during the ide-probe at boot. It is reported to support DVD
+  II drives, by the manufacturer.
 
   Please read the comments at the top of drivers/block/hpt343.c
 
 QDI QD6580 support
 CONFIG_BLK_DEV_QD6580
   This driver is enabled at runtime using the "ide0=qd6580" kernel
-  boot parameter.  It permits faster I/O speeds to be set.  See the
+  boot parameter. It permits faster I/O speeds to be set. See the
   files Documentation/ide.txt and qd6580.c for more info.
 
 UMC 8672 support
 CONFIG_BLK_DEV_UMC8672
   This driver is enabled at runtime using the "ide0=umc8672" kernel
-  boot parameter.  It enables support for the secondary IDE interface
+  boot parameter. It enables support for the secondary IDE interface
   of the UMC-8672, and permits faster I/O speeds to be set as well.
   See the files Documentation/ide.txt and umc8672.c for more info.
 
 ALI M14xx support
 CONFIG_BLK_DEV_ALI14XX
   This driver is enabled at runtime using the "ide0=ali14xx" kernel
-  boot parameter.  It enables support for the secondary IDE interface
+  boot parameter. It enables support for the secondary IDE interface
   of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
   I/O speeds to be set as well. See the files Documentation/ide.txt
   and ali14xx.c for more info.
@@ -620,12 +655,12 @@ CONFIG_PARIDE
 Parallel port IDE disks
 CONFIG_PARIDE_PD
   This option enables the high-level driver for IDE-type disk devices 
-  connected through a parallel port.  If you chose to build PARIDE 
+  connected through a parallel port. If you chose to build PARIDE 
   support into your kernel, you may answer Y here to build in the 
   parallel port IDE driver, otherwise you should answer M to build 
-  it as a loadable module.  The module will be called pd.o.  You 
+  it as a loadable module. The module will be called pd.o. You 
   must also have at least one parallel port protocol driver in your 
-  system.  Among the devices supported by this driver are the SyQuest 
+  system. Among the devices supported by this driver are the SyQuest 
   EZ-135, EZ-230 and SparQ drives, the Avatar Shark and the backpack
   hard drives from MicroSolutions.
 
@@ -639,31 +674,31 @@ CONFIG_PARIDE_PCD
   must also have at least one parallel port protocol driver in your
   system. Among the devices supported by this driver are the
   MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If
-  you have such a CD-ROM drive, you should also say Y or M to "ISO 9660
-  CDROM filesystem support" below, because that's the filesystem used
-  on CDROMs.
+  you have such a CD-ROM drive, you should also say Y or M to "ISO
+  9660 CDROM filesystem support" below, because that's the filesystem
+  used on CDROMs.
 
 Parallel port ATAPI disks
 CONFIG_PARIDE_PF
   This option enables the high-level driver for ATAPI disk devices
-  connected through a parallel port.  If you chose to build PARIDE
+  connected through a parallel port. If you chose to build PARIDE
   support into your kernel, you may answer Y here to build in the
   parallel port ATAPI disk driver, otherwise you should answer M
-  to build it as a loadable module.  The module will be called pf.o.
+  to build it as a loadable module. The module will be called pf.o.
   You must also have at least one parallel port protocol driver in
-  your system.  Among the devices supported by this driver are the
+  your system. Among the devices supported by this driver are the
   MicroSolutions backpack PD/CD drive and the Imation Superdisk
   LS-120 drive.
 
 Parallel port ATAPI tapes
 CONFIG_PARIDE_PT
   This option enables the high-level driver for ATAPI tape devices
-  connected through a parallel port.  If you chose to build PARIDE
+  connected through a parallel port. If you chose to build PARIDE
   support into your kernel, you may answer Y here to build in the
   parallel port ATAPI disk driver, otherwise you should answer M
-  to build it as a loadable module.  The module will be called pt.o.
+  to build it as a loadable module. The module will be called pt.o.
   You must also have at least one parallel port protocol driver in
-  your system.  Among the devices supported by this driver is the
+  your system. Among the devices supported by this driver is the
   parallel port version of the HP 5GB drive.
 
 Parallel port generic ATAPI devices
@@ -671,54 +706,59 @@ CONFIG_PARIDE_PG
   This option enables a special high-level driver for generic ATAPI
   devices connected through a parallel port. The driver allows user
   programs, such as cdrecord, to send ATAPI commands directly to a
-  device. If you chose to build PARIDE support into your kernel, you 
-  may answer Y here to build in the parallel port generic ATAPI driver, 
-  otherwise you should answer M to build it as a loadable module.
-  The module will be called pg.o.  You must also have at least one 
-  parallel port protocol driver in your system.  This driver 
-  implements an API loosely related to the generic SCSI driver.  
-  See /usr/include/linux/pg.h for details. 
+  device. 
+
+  If you chose to build PARIDE support into your kernel, you may
+  answer Y here to build in the parallel port generic ATAPI driver,
+  otherwise you should answer M to build it as a loadable module. The
+  module will be called pg.o.
+
+  You must also have at least one parallel port protocol driver in
+  your system.
+
+  This driver implements an API loosely related to the generic SCSI
+  driver. See /usr/include/linux/pg.h for details.
 
   You can obtain the most recent version of cdrecord from
-  ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ .  Versions 1.6.1a3 and
-  later fully support the pg driver.
+  ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and
+  later fully support this driver.
 
 ATEN EH-100 protocol
 CONFIG_PARIDE_ATEN
   This option enables support for the ATEN EH-100 parallel port IDE
-  protocol.  This protocol is used in some inexpensive low performance 
-  parallel port kits made in Hong Kong. If you chose to build PARIDE 
-  support into your kernel, you may answer Y here to build in the 
-  protocol driver, otherwise you should answer M to build it as a 
-  loadable module.  The module will be called aten.o.  You must also 
-  have a high-level driver for the type of device that you want to 
+  protocol. This protocol is used in some inexpensive low performance
+  parallel port kits made in Hong Kong. If you chose to build PARIDE
+  support into your kernel, you may answer Y here to build in the
+  protocol driver, otherwise you should answer M to build it as a
+  loadable module. The module will be called aten.o. You must also
+  have a high-level driver for the type of device that you want to
   support.
 
 MicroSolutions backpack protocol
 CONFIG_PARIDE_BPCK
-  This option enables support for the MicroSolutions backpack 
-  parallel port IDE protocol.  If you chose to build PARIDE support
-  into your kernel, you may answer Y here to build in the protocol
-  driver, otherwise you should answer M to build it as a loadable
-  module.  The module will be called bpck.o.  You must also have
-  a high-level driver for the type of device that you want to support.
+  This option enables support for the MicroSolutions backpack parallel
+  port IDE protocol. If you chose to build PARIDE support into your
+  kernel, you may answer Y here to build in the protocol driver,
+  otherwise you should answer M to build it as a loadable module. The
+  module will be called bpck.o. You must also have a high-level driver
+  for the type of device that you want to support.
 
 DataStor Commuter protocol
 CONFIG_PARIDE_COMM
   This option enables support for the Commuter parallel port IDE 
-  protocol from DataStor.  If you chose to build PARIDE support
+  protocol from DataStor. If you chose to build PARIDE support
   into your kernel, you may answer Y here to build in the protocol
   driver, otherwise you should answer M to build it as a loadable
-  module.  The module will be called comm.o.  You must also have
+  module. The module will be called comm.o. You must also have
   a high-level driver for the type of device that you want to support.
 
 DataStor EP-2000 protocol
 CONFIG_PARIDE_DSTR
   This option enables support for the EP-2000 parallel port IDE 
-  protocol from DataStor.  If you chose to build PARIDE support
+  protocol from DataStor. If you chose to build PARIDE support
   into your kernel, you may answer Y here to build in the protocol
   driver, otherwise you should answer M to build it as a loadable
-  module.  The module will be called dstr.o.  You must also have
+  module. The module will be called dstr.o. You must also have
   a high-level driver for the type of device that you want to support.
 
 Shuttle EPAT/EPEZ protocol
@@ -767,11 +807,11 @@ CONFIG_PARIDE_FIT3
 
 FreeCom power protocol
 CONFIG_PARIDE_FRPW
-  This option enables support for the Freecom power parallel port IDE 
-  protocol.  If you chose to build PARIDE support into your kernel, you 
-  may answer Y here to build in the protocol driver, otherwise you 
-  should answer M to build it as a loadable module.  The module will be 
-  called frpw.o.  You must also have a high-level driver for the type 
+  This option enables support for the Freecom power parallel port IDE
+  protocol. If you chose to build PARIDE support into your kernel, you
+  may answer Y here to build in the protocol driver, otherwise you
+  should answer M to build it as a loadable module. The module will be
+  called frpw.o. You must also have a high-level driver for the type
   of device that you want to support.
 
 KingByte KBIC-951A/971A protocols
@@ -788,11 +828,11 @@ CONFIG_PARIDE_KBIC
 KT PHd protocol
 CONFIG_PARIDE_KTTI
   This option enables support for the "PHd" parallel port IDE protocol
-  from KT Technology.  This is a simple (low speed) adapter that is
-  used in some 2.5" portable hard drives.  If you chose to build PARIDE 
-  support into your kernel, you may answer Y here to build in the 
-  protocol driver, otherwise you should answer M to build it as a 
-  loadable module.  The module will be called ktti.o.  You must also 
+  from KT Technology. This is a simple (low speed) adapter that is
+  used in some 2.5" portable hard drives. If you chose to build PARIDE
+  support into your kernel, you may answer Y here to build in the
+  protocol driver, otherwise you should answer M to build it as a
+  loadable module. The module will be called ktti.o. You must also
   have a high-level driver for the type of device that you want to
   support.
 
@@ -800,43 +840,52 @@ OnSpec 90c20 protocol
 CONFIG_PARIDE_ON20
   This option enables support for the (obsolete) 90c20 parallel port 
   IDE protocol from OnSpec (often marketed under the ValuStore brand
-  name).  If you chose to build PARIDE support into your kernel, you 
+  name). If you chose to build PARIDE support into your kernel, you 
   may answer Y here to build in the protocol driver, otherwise you 
-  should answer M to build it as a loadable module.  The module will 
-  be called on20.o.  You must also have a high-level driver for the 
+  should answer M to build it as a loadable module. The module will 
+  be called on20.o. You must also have a high-level driver for the 
   type of device that you want to support.
 
 OnSpec 90c26 protocol
 CONFIG_PARIDE_ON26
-  This option enables support for the 90c26 parallel port IDE protocol 
+  This option enables support for the 90c26 parallel port IDE protocol
   from OnSpec Electronics (often marketed under the ValuStore brand
-  name).  If you chose to build PARIDE support into your kernel, you 
-  may answer Y here to build in the protocol driver, otherwise you 
-  should answer M to build it as a loadable module.  The module will 
-  be called on26.o.  You must also have a high-level driver for the 
-  type of device that you want to support.
+  name). If you chose to build PARIDE support into your kernel, you
+  may answer Y here to build in the protocol driver, otherwise you
+  should answer M to build it as a loadable module. The module will be
+  called on26.o. You must also have a high-level driver for the type
+  of device that you want to support.
 
 Multiple devices driver support
 CONFIG_BLK_DEV_MD
   This driver lets you combine several hard disk partitions into one
-  logical block device. This can be used to combine several redundant
+  logical block device. This can be used to simply append one
+  partition to another one or to combine several redundant
   hard disks to a RAID1/4/5 device so as to provide protection against
-  hard disk failures. More information and the necessary tools are
-  available over FTP (user: anonymous) from
-  ftp://sweet-smoke.ufr-info-p7.ibp.fr/pub/Linux in the md package and
-  the md-FAQ. Please read drivers/block/README.md and the relevant
-  section of the Disk-HOWTO, available via FTP (user: anonymous) from
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. If unsure, say N.
+  hard disk failures. This is called "Software RAID" since the
+  combining of the partitions is done by the kernel. "Hardware RAID"
+  means that the combining is done by a dedicated controller; if you
+  have such a controller, you do not need to say Y here.
+
+  More information about Software RAID on Linux is contained in the
+  Software-RAID mini-HOWTO, available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also
+  learn where to get the supporting user space utilities raidtools.
+
+  If unsure, say N.
 
 Linear (append) mode
 CONFIG_MD_LINEAR
   If you say Y here, then your multiple devices driver will be able to
   use the so-called linear mode, i.e. it will combine the hard disk
-  partitions by simply appending one to the other. 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. The module will be called
-  linear.o. If unsure, say Y.
+  partitions by simply appending one to the other. 
+
+  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. The module will be
+  called linear.o.
+
+  If unsure, say Y.
 
 RAID-0 (striping) mode
 CONFIG_MD_STRIPED
@@ -844,31 +893,19 @@ CONFIG_MD_STRIPED
   use the so-called raid0 mode, i.e. it will combine the hard disk
   partitions into one logical device in such a fashion as to fill them
   up evenly, one chunk here and one chunk there. This will increase
-  the throughput rate if the partitions reside on distinct disks.  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. The module will be called
-  raid0.o. If unsure, say Y.
+  the throughput rate if the partitions reside on distinct disks. 
 
-Are you using a crosscompiler
-CONFIG_CROSSCOMPILE
-  Set this if you are using another architecture to compile the
-  kernel for your MIPS machine.
+  Information about Software RAID on Linux is contained in the
+  Software-RAID mini-HOWTO, available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also
+  learn where to get the supporting user space utilities raidtools.
 
-Support for Acer PICA 1 chipset
-CONFIG_ACER_PICA_61
-  This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
-  kernel that runs on these, say Y here. For details about Linux on
-  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-  http://lena.fnet.fr/ (To browse the WWW, you need to have access to
-  a machine on the Internet that has a program like lynx or
-  netscape).
+  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. The module will be
+  called raid0.o.
 
-Support for Algorithmics P4032
-CONFIG_ALGOR_P4032
-  This is an evaluation board of the British company Algorithmics.  The
-  board uses the R4300 and a R5230 CPUs.  For more information about
-  this board see www.algor.co.uk.
+  If unsure, say Y.
 
 RAID-1 (mirroring) mode
 CONFIG_MD_MIRRORING
@@ -878,23 +915,20 @@ CONFIG_MD_MIRRORING
   an error free MD (multiple device) to the higher levels of the
   kernel. In a set with N drives, the available space is the capacity
   of a single drive, and the set protects against a failure of (N - 1)
-  drives.  
+  drives. 
 
-  Raidtools, a set of user-space tools which create and maintain
-  RAID1/4/5 sets, is available at:
-  ftp://ftp.kernel.org/pub/linux/daemons/raid
-  http://luthien.nuclecu.unam.mx/~miguel/raid
+  Information about Software RAID on Linux is contained in the
+  Software-RAID mini-HOWTO, available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also
+  learn where to get the supporting user space utilities raidtools.
 
   If you want to use such a RAID-1 set, say Y. This code is also
   available as a module called raid1.o ( = 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. If unsure, say Y.
+  Documentation/modules.txt.
 
-Boot support (linear, striped)
-CONFIG_MD_BOOT
-  To boot with an initial linear or striped md device you have to say
-  Y here. For lilo and loadlin options see Documentation/md.txt.
+  If unsure, say Y.
 
 RAID-4/RAID-5 mode
 CONFIG_MD_RAID5
@@ -906,16 +940,47 @@ CONFIG_MD_RAID5
   while a RAID-5 set distributes the parity across the drives in one
   of the available parity distribution methods.
 
-  Raidtools, a set of user-space tools which create and maintain
-  RAID1/4/5 sets, is available at:
-  ftp://ftp.kernel.org/pub/linux/daemons/raid
-  http://luthien.nuclecu.unam.mx/~miguel/raid
+  Information about Software RAID on Linux is contained in the
+  Software-RAID mini-HOWTO, available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also
+  learn where to get the supporting user space utilities raidtools.
 
-  If you want to use such a RAID-5 set, say Y. This code is also
-  available as a module called raid5.o ( = 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. If unsure, say Y.
+  If you want to use such a RAID-4/RAID-5 set, say Y. This code is
+  also available as a module called raid5.o ( = 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.
+
+  If unsure, say Y.
+
+Boot support (linear, striped)
+CONFIG_MD_BOOT
+  To boot with an initial linear or striped md device you have to
+  answer Y here. For lilo and loadlin options see the file
+  Documentation/md.txt.
+
+Support for Deskstation RPC44 
+CONFIG_DESKSTATION_RPC44
+  This is a machine with a R4400 100 MHz CPU. To compile a Linux
+  kernel that runs on these, say Y here. For details about Linux
+  on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+  http://lena.fnet.fr/ (To browse the WWW, you need to
+  have access to a machine on the Internet that has a program like
+  lynx or netscape).
+
+Support for Acer PICA 1 chipset
+CONFIG_ACER_PICA_61
+  This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
+  kernel that runs on these, say Y here. For details about Linux on
+  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+  http://lena.fnet.fr/ (To browse the WWW, you need to have access to
+  a machine on the Internet that has a program like lynx or netscape).
+
+Support for Algorithmics P4032
+CONFIG_ALGOR_P4032
+  This is an evaluation board of the British company Algorithmics. The
+  board uses the R4300 and a R5230 CPUs. For more information about
+  this board see http://www.algor.co.uk.
 
 Support for Mips Magnum 4000
 CONFIG_MIPS_MAGNUM_4000
@@ -935,27 +1000,27 @@ CONFIG_OLIVETTI_M700
 
 CPU type
 CONFIG_CPU_R3000
-  Give the type of your machine's MIPS CPU. For this question,
-  it suffices to give a unique prefix of the option you want to
-  choose.  In case of doubt select the R3000 CPU.  This kernel will
-  run on other MIPS machines but with slightly reduced performance.
+  Give the type of your machine's MIPS CPU. For this question, it
+  suffices to give a unique prefix of the option you want to choose.
+  In case of doubt select the R3000 CPU. The kernel will then run on
+  other MIPS machines but with slightly reduced performance.
 
 Compile the kernel into the ECOFF object format
 CONFIG_ECOFF_KERNEL
-  Some machines require a kernel in the ECOFF format.  You will have to
-  Choose this option for example if you want to a Mips Magnum 3000 or a
-  DECstation over network.
+  Some machines require a kernel in the ECOFF format. You will have to
+  say Y here for example if you want to use a Mips Magnum 3000 or a
+  DECstation.
 
 Generate little endian code
 CONFIG_CPU_LITTLE_ENDIAN
   Some MIPS machines can be configured for either little or big endian
-  byte order.  Both modes require different kernels.  Say yes if your
-  machine is little endian, no if it's a big endian machine.
+  byte order. These modes require different kernels. Say Y if your
+  machine is little endian, N if it's a big endian machine.
 
 Kernel support for IRIX binaries
 CONFIG_BINFMT_IRIX
-  This option enables the kernel support for IRIX binaries.  Running
-  IRIX binaries additionally requires IRIX libraries.
+  If you say Y here, the kernel will support running of IRIX binaries.
+  You will need IRIX libraries for this to work.
 
 Networking support
 CONFIG_NET
@@ -1036,10 +1101,11 @@ CONFIG_FIREWALL
 
 SYN flood protection
 CONFIG_SYN_COOKIES
-  Normal TCP/IP networking is open to an attack known as "SYN flooding".
-  This denial-of-service attack prevents legitimate remote users from
-  being able to connect to your computer and requires very little work
-  from the attacker, who can operate from anywhere on the Internet.
+  Normal TCP/IP networking is open to an attack known as "SYN
+  flooding". This denial-of-service attack prevents legitimate remote
+  users from being able to connect to your computer during an ongoing
+  attack and requires very little work from the attacker, who can
+  operate from anywhere on the Internet.
 
   SYN cookies provide protection against this type of attack. If you
   say Y here, the TCP/IP stack will use a cryptographic challenge
@@ -1055,6 +1121,10 @@ CONFIG_SYN_COOKIES
   an aid in tracing the packets to their actual source and should not
   be taken as absolute truth.
 
+  SYN cookies may prevent correct error reporting on clients when the
+  server is really overloaded. If this happens frequently better turn
+  them off.
+
   If you say Y here, note that SYN cookies aren't enabled by default;
   you can enable them by saying Y to "/proc filesystem support" and
   "Sysctl support" below and executing the command
@@ -1081,7 +1151,7 @@ CONFIG_ALPHA_AVANTI
   question, it suffices to give a unique prefix of the option you want
   to choose. The choices:
   ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400)
-     AlphaStations.  These usually come with a TGA graphics adapter,
+     AlphaStations. These usually come with a TGA graphics adapter,
      so you'll want to say Y to "TGA Console support", below, if you
      have one of these.
   ** Alpha-XL: A.k.a. "Windows NT Dream Machine" :-) These usually 
@@ -1134,20 +1204,24 @@ CONFIG_SERIAL_NONSTANDARD
   This includes intelligent serial boards such as Cyclades,
   Digiboards, etc. These are usually used for systems that need many
   serial ports because they serve many terminals or dial-in
-  connections.  Note that the answer to this question won't directly
-  affect the kernel: saying N will just cause this configure script to
-  skip all the questions about non-standard serial boards. Most people
-  can say N here.
+  connections. 
+
+  Note that the answer to this question won't directly affect the
+  kernel: saying N will just cause this configure script to skip all
+  the questions about non-standard serial boards. 
+
+  Most people can say N here.
 
 Extended dumb serial driver options
 CONFIG_SERIAL_EXTENDED
   If you wish to use any non-standard features of the standard "dumb"
-  driver, say Y here.  This includes HUB6 support, shared serial
+  driver, say Y here. This includes HUB6 support, shared serial
   interrupts, special multiport support, support for more than the
-  four COM 1/2/3/4 boards, etc.  Note that the answer to this question
-  won't directly affect the kernel: saying N will just cause this
-  configure script to skip all the questions about serial driver
-  options. If unsure, say N.
+  four COM 1/2/3/4 boards, etc. 
+
+  Note that the answer to this question won't directly affect the
+  kernel: saying N will just cause this configure script to skip all
+  the questions about serial driver options. If unsure, say N.
 
 Support more than 4 serial ports
 CONFIG_SERIAL_MANY_PORTS
@@ -1164,7 +1238,7 @@ CONFIG_SERIAL_MANY_PORTS
 Support for sharing serial interrupts
 CONFIG_SERIAL_SHARE_IRQ
   Some serial boards have hardware support which allows multiple dumb
-  serial ports on the same board to share a single IRQ.  To enable
+  serial ports on the same board to share a single IRQ. To enable
   support for this in the serial driver, say Y here.
 
 Auto detect IRQ on standard ports (unsafe)
@@ -1181,26 +1255,20 @@ Support special multiport boards
 CONFIG_SERIAL_MULTIPORT
   Some multiport serial ports have special ports which are used to
   signal when there are any serial ports on the board which need
-  servicing.  Say Y here to enable the serial driver to take advantage
+  servicing. Say Y here to enable the serial driver to take advantage
   of those special I/O ports.
 
 SGI Zilog85C30 serial support
 CONFIG_SGI_SERIAL
-  If you want to use your SGI's built-in serial ports under Linux, say Y.
+  If you want to use your SGI's built-in serial ports under Linux,
+  answer Y.
 
 SGI graphics support
 CONFIG_SGI_GRAPHICS
-  If you have an SGI machine and you want to compile the graphic drivers
-  select this option.  This will include the code for the /dev/graphics
-  and /dev/gfx drivers into the kernel for supporting the virtualized
-  access to your graphics hardware.
-
-Remote GDB kernel debugging
-CONFIG_REMOTE_DEBUG
-  This enables remote debugging support for the MIPS kernel.  Enabling
-  this option enlarges you kernel image disk size by several megabytes
-  and requires a machine with more than 16mb, better 32mb RAM to avoid
-  excessive linking time.
+  If you have an SGI machine and you want to compile the graphics
+  drivers, say Y here. This will include the code for the
+  /dev/graphics and /dev/gfx drivers into the kernel for supporting
+  virtualized access to your graphics hardware.
 
 Support the Bell Technologies HUB6 card
 CONFIG_HUB6
@@ -1238,10 +1306,10 @@ PCI direct access support
 CONFIG_PCI_DIRECT
   If you don't want to use the PCI BIOS (e.g., because you run some
   embedded system with no BIOS at all) or Linux says it cannot use
-  your PCI BIOS, you can enable direct PCI hardware here. It might fail
-  if your machine is based on some unusual chipset, but it usually
-  works. If both PCI BIOS and direct PCI access are enabled, the use
-  of BIOS is preferred. If unsure, say Y.
+  your PCI BIOS, you can enable direct PCI hardware here. It might
+  fail if your machine is based on some unusual chipset, but it
+  usually works. If both PCI BIOS and direct PCI access are enabled,
+  the use of BIOS is preferred. If unsure, say Y.
 
 PCI quirks
 CONFIG_PCI_QUIRKS
@@ -1253,9 +1321,9 @@ CONFIG_PCI_QUIRKS
 PCI bridge optimization (experimental)
 CONFIG_PCI_OPTIMIZE
   This can improve access times for some hardware devices if you have
-  a really broken BIOS and your computer uses a PCI bus system. Set to
-  Y if you think it might help, but try turning it off if you
-  experience any problems with the PCI bus. N is the safe answer.
+  a really broken BIOS and your computer uses a PCI bus system. Say Y
+  if you think it might help, but try turning it off if you experience
+  any problems with the PCI bus. N is the safe answer.
 
 Backward-compatible /proc/pci
 CONFIG_PCI_OLD_PROC
@@ -1275,15 +1343,15 @@ If you say Y here and to the "/proc filesystem support" below, you
 MCA support
 CONFIG_MCA
   MicroChannel Architecture is found in some IBM PS/2 machines and
-  laptops. It is a bus system similar to PCI or ISA.  See
+  laptops. It is a bus system similar to PCI or ISA. See
   Documentation/mca.txt (and especially the web page given there)
-  before attempting to build an MCA bus kernel.  Note that this is
+  before attempting to build an MCA bus kernel. Note that this is
   still experimental code.
 
 System V IPC
 CONFIG_SYSVIPC
   Inter Process Communication is a suite of library functions and
-  system calls which let processes (running programs) synchronize
+  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 say Y here. In
   particular, if you want to run the DOS emulator dosemu under Linux
@@ -1296,7 +1364,7 @@ CONFIG_SYSVIPC
   (user: anonymous) from
   ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide.
 
-  Saying Y here enlarges your kernel by about 7kB. Just say Y.
+  Saying Y here enlarges your kernel by about 7 KB. Just say Y.
 
 BSD Process Accounting
 CONFIG_BSD_PROCESS_ACCT
@@ -1319,31 +1387,33 @@ CONFIG_SYSCTL
   enabled, a tree of modifiable sysctl entries will be generated
   beneath the /proc/sys directory. They are explained in the files in
   Documentation/sysctl/. Note that enabling this option will enlarge
-  the kernel by at least 8kB. As it is generally a good thing, you
-  should say Y here unless building a kernel for install/rescue disks
-  or your system is very limited in memory.
+  the kernel by at least 8 KB. 
+
+  As it is generally a good thing, you should say Y here unless
+  building a kernel for install/rescue disks or your system is very
+  limited in memory.
 
 Kernel support for ELF binaries
 CONFIG_BINFMT_ELF
   ELF (Executable and Linkable Format) is a format for libraries and
   executables used across different architectures and operating
-  systems. Saying Y here will enable your kernel to run ELF binaries and
-  enlarge it by about 2kB. ELF support under Linux has now all but
-  replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
+  systems. Saying Y here will enable your kernel to run ELF binaries
+  and enlarge it by about 2 KB. ELF support under Linux has now all
+  but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
   because it is portable (this does *not* mean that you will be able
-  to run executables from different architectures or operating
-  systems!) and makes building run-time libraries very easy. Many new
+  to run executables from different architectures or operating systems
+  however) and makes building run-time libraries very easy. Many new
   executables are distributed solely in ELF format. You definitely
-  want to say Y here. 
+  want to say Y here.
 
-  Information about ELF is on the WWW at
-  http://www.sjc.ox.ac.uk/users/barlow/elf-howto.html (to browse the
-  WWW, you need to have access to a machine on the Internet that has a
-  program like lynx or netscape). If you find that after upgrading
-  from Linux kernel 1.2 and saying Y here, you still can't run any ELF
-  binaries (they just crash), then you'll have to install the newest
-  ELF runtime libraries, including ld.so (check the file
-  Documentation/Changes for location and latest version).
+  Information about ELF is contained in the ELF HOWTO available via
+  FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+  If you find that after upgrading from Linux kernel 1.2 and saying Y
+  here, you still can't run any ELF binaries (they just crash), then
+  you'll have to install the newest ELF runtime libraries, including
+  ld.so (check the file Documentation/Changes for location and latest
+  version).
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -1389,14 +1459,14 @@ CONFIG_BINFMT_JAVA
 
   Saying Y here allows you to execute a JAVA bytecode binary just like
   any other Linux program: by simply typing in its name. (You also
-  need to have the JDK installed for this to work).  As more and more
+  need to have the JDK installed for this to work). As more and more
   Java programs become available, the use for this will gradually
-  increase. You can even execute HTML files containing JAVA applets 
-  (= JAVA binaries) if those files start with the string
+  increase. You can even execute HTML files containing JAVA applets
+  (little embedded JAVA binaries) if those files start with the string
   "<!--applet-->". If you want to use this, say Y here and read
-  Documentation/java.txt. 
+  Documentation/java.txt.
 
-  If you disable this option it will reduce your kernel by about 4kB.
+  If you disable this option it will reduce your kernel by about 4 KB.
   This is not much and by itself does not warrant removing support.
   However its removal is a good idea if you do not have the JDK
   installed. You may answer M for module support and later load the
@@ -1417,7 +1487,7 @@ CONFIG_BINFMT_EM86
   this to work, you need to have the emulator /usr/bin/em86 in place.
   You may answer M to compile the emulation support as a module and
   later load the module when you want to use a Linux/Intel binary. The
-  module will be called binfmt_em86.o.  If unsure, say Y.
+  module will be called binfmt_em86.o. If unsure, say Y.
 
 Kernel support for MISC binaries
 CONFIG_BINFMT_MISC
@@ -1450,7 +1520,7 @@ CONFIG_BINFMT_MISC
 Solaris binary emulation
 CONFIG_SOLARIS_EMUL
   This is experimental code which will enable you to run (many)
-  Solaris binaries on your SPARC Linux machine.  
+  Solaris binaries on your SPARC Linux machine. 
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -1462,11 +1532,23 @@ CONFIG_M386
   This is the processor type of your CPU. This information is used for
   optimizing purposes. In order to compile a kernel that can run on
   all x86 CPU types (albeit not optimally fast), you can specify
-  "386" here.  If you specify one of "486" or "Pentium" or "PPro",
-  then the kernel will run on all of these CPUs: 486 and Pentium
-  (=586) and Pentium Pro (=686). In rare cases, it can make sense to
-  specify "Pentium" even if running on a 486: the kernel will be
-  smaller but slower. 
+  "386" here. If you specify one of "486" or "Pentium" or "PPro",
+  then the kernel will run on all x86 architectures except on 386.
+
+  Here are the settings recommended for greatest speed:
+   - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX and
+     Cyrix/TI 486DLC/DLC2. Only "386" kernels will run on a 386 class
+     machine.
+   - "486" for the AMD/Cyrix/IBM/Intel DX4 or 486DX/DX2/SL/SX/SX2,
+     AMD/Cyrix 5x86, NexGen Nx586 and UMC U5D or U5S
+   - "Pentium" for the AMD K5, K6 and K6-3D, Cyrix MediaGX,
+     Cyrix/IBM/National Semiconductor 6x86 and GXm, IDT Centaur
+     WinChip C6, and Intel Pentium/Pentium MMX
+   - "PPro" for the Cyrix/IBM/National Semiconductor 6x86MX, MII and
+     Intel Pentium II/Pentium Pro
+
+  In rare cases, it can make sense to specify "Pentium" even if
+  running on a 486: the kernel will be smaller but slower.
 
   If you have a single processor machine, make sure that the line
   "SMP=1" at the top of the toplevel kernel Makefile is commented out;
@@ -1479,12 +1561,12 @@ CONFIG_M386
   like lynx or netscape). People using multiprocessor machines should
   also say Y to "Enhanced Real Time Clock Support", below.
 
-  If you want to compile a kernel that should work on both single
-  processor and multi processor machines, it is possible to set SMP=1.
-  The "Advanced Power Management" code (see configuration option
-  below) will not work in that scenario, though. In addition, the
-  kernel will be slower on single processor machines, and other
-  problems may appear, so this is not recommended.
+  If you want to compile a kernel that works on both single processor
+  and multi processor machines, it is possible to set SMP=1. The
+  "Advanced Power Management" code (see configuration option below)
+  will not work in that scenario, though. In addition, the kernel will
+  be slower on single processor machines, and other problems may
+  appear, so this is not recommended.
 
   If you don't know what to do, choose "386".
 
@@ -1492,7 +1574,13 @@ VGA text console
 CONFIG_VGA_CONSOLE
   Saying Y here will allow you to use Linux in text mode through a
   display that complies with the generic VGA standard. Virtually
-  everyone wants that. Say Y.
+  everyone wants that. 
+
+  The program SVGATextMode can be used to utilize SVGA video cards to
+  their full potential in text mode. Download it via FTP (user:
+  anonymous) from ftp://sunsite.unc.edu/pub/Linux/utils/console.
+
+  Say Y.
 
 Video mode selection support
 CONFIG_VIDEO_SELECT
@@ -1528,13 +1616,15 @@ CONFIG_FB
   in the /dev directory, i.e. /dev/fb*.
 
   You need an utility program called fbset to make full use of frame
-  buffer devices. Please read the file
-  Documentation/fb/framebuffer.txt for more information.
+  buffer devices. Please read Documentation/fb/framebuffer.txt and the
+  Framebuffer-HOWTO at
+  http://www.tahallah.demon.co.uk/programming/prog.html for more
+  information.
 
-  If you want to play with it, say Y here and also to the driver for
-  your graphics board, below. If unsure, say N, unless you are
-  compiling a kernel for a non-X86 architecture, in which case you
-  should say Y.
+  Say Y here and to the driver for your graphics board below if you
+  are compiling a kernel for a non-x86 architecture. If you are
+  compiling for the x86 architecture, you can say Y if you want to
+  play with it, but it is not essential.
 
 Acorn VIDC support
 CONFIG_FB_ACORN
@@ -1554,13 +1644,13 @@ CONFIG_FB_AMIGA
 Amiga OCS chipset support
 CONFIG_FB_AMIGA_OCS
   This enables support for the original Agnus and Denise video chips,
-  found in the Amiga 1000 and most A500's and A2000's.  If you intend
+  found in the Amiga 1000 and most A500's and A2000's. If you intend
   to run Linux on any of these systems, say Y; otherwise say N.
 
 Amiga ECS chipset support
 CONFIG_FB_AMIGA_ECS
   This enables support for the Enhanced Chip Set, found in later
-  A500's, later A2000's, the A600, the A3000, the A3000T and CDTV.  If
+  A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
   you intend to run Linux on any of these systems, say Y; otherwise
   say N.
 
@@ -1568,7 +1658,7 @@ Amiga AGA chipset support
 CONFIG_FB_AMIGA_AGA
   This enables support for the Advanced Graphics Architecture (also
   known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
-  and CD32.  If you intend to run Linux on any of these systems, say Y;
+  and CD32. If you intend to run Linux on any of these systems, say Y;
   otherwise say N.
 
 Amiga CyberVision support
@@ -1609,7 +1699,8 @@ CONFIG_FB_ATARI
 
 Open Firmware frame buffer device support 
 CONFIG_FB_OF
-  Say Y if you want support with Open Firmware for your graphics board.
+  Say Y if you want support with Open Firmware for your graphics
+  board.
 
 S3 Trio frame buffer device support 
 CONFIG_FB_S3TRIO
@@ -1626,13 +1717,13 @@ CONFIG_FB_CONTROL
 
 PowerMac "platinum" frame buffer device support
 CONFIG_FB_PLATINUM
-  This driver supports a frame buffer for the "platinum" graphics adapter
-  in some Power Macintoshes.
+  This driver supports a frame buffer for the "platinum" graphics
+  adapter in some Power Macintoshes.
 
 PowerMac "valkyrie" frame buffer device support
 CONFIG_FB_VALKYRIE
-  This driver supports a frame buffer for the "valkyrie" graphics adapter
-  in some Power Macintoshes.
+  This driver supports a frame buffer for the "valkyrie" graphics
+  adapter in some Power Macintoshes.
 
 Chips 65550 display support
 CONFIG_FB_CT65550
@@ -1651,29 +1742,39 @@ CONFIG_FB_HP300
 
 TGA frame buffer support
 CONFIG_FB_TGA
-  This is the frame buffer device driver for generic TGA graphic cards.
-  Say Y if you have one of those.
+  This is the frame buffer device driver for generic TGA graphic
+  cards. Say Y if you have one of those.
 
 VESA VGA graphics console
 CONFIG_FB_VESA
-  This is the frame buffer device driver for generic VESA graphic cards.
-  Please read Documentation/fb/vesafb.txt.
+  This is the frame buffer device driver for generic VESA 2.0
+  compliant graphic cards. The older VESA 1.2 cards are not supported.
+  You will get a boot time penguin logo at no additional cost. Please
+  read Documentation/fb/vesafb.txt and the . If unsure, say Y.
+
+Backward compatibility mode for Xpmac
+CONFIG_FB_COMPAT_XPMAC
+  If you use the Xpmac X server (common with mklinux), you'll need
+  to enable this to use X. You should consider changing to XFree86
+  which includes a server that supports the frame buffer device
+  directly (XF68_FBDev).
 
 MDA text console (dual-headed)
 CONFIG_MDA_CONSOLE
   Say Y here if you have an old MDA or monochrome Hercules graphics
-  adapter in your system acting as a second head ( = video card).  Do 
-  not enable this driver if your MDA card is the primary card in your
-  system; the normal VGA driver will handle it.
+  adapter in your system acting as a second head ( = video card). You
+  will then be able to use two monitors with your Linux system. Do not
+  say Y here if your MDA card is the primary card in your system; the
+  normal VGA driver will handle it.
   
   This driver is also available as a module ( = code which can be
   inserted and removed from the running kernel whenever you want).
-  The module will be called mdacon.o.  If you want to compile it as
+  The module will be called mdacon.o. If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
   
   If unsure, say N.
 
-SBUS and UPA framebuffers
+SBUS and UPA frame buffers
 CONFIG_FB_SBUS
   Say Y if you want support for SBUS or UPA based frame buffer device.
 
@@ -1697,7 +1798,8 @@ CONFIG_FB_CGTHREE
 
 TCX (SS4/SS5 only) support
 CONFIG_FB_TCX
-  This is the frame buffer device driver for the TCX 24/8bit frame buffer.
+  This is the frame buffer device driver for the TCX 24/8bit frame
+  buffer.
 
 Virtual Frame Buffer support (ONLY FOR TESTING!)
 CONFIG_FB_VIRTUAL
@@ -1711,19 +1813,19 @@ CONFIG_FB_VIRTUAL
   kernel option `video=vfb:'.
 
   This driver is also available as a module ( = code which can be
-  inserted and removed from the running kernel whenever you want).
-  The module will be called vfb.o.  If you want to compile it as
-  a module, say M here and read Documentation/modules.txt.
+  inserted and removed from the running kernel whenever you want). The
+  module will be called vfb.o. If you want to compile it as a module,
+  say M here and read Documentation/modules.txt.
  
   If unsure, say N.
 
 Advanced low level driver options
 CONFIG_FBCON_ADVANCED
   The frame buffer console uses character drawing routines that are
-  tailored to the specific organization of pixels in the memory of your
-  graphics hardware.  These are called the low level frame buffer console
-  drivers. Note that they are used for text console output only; they are
-  NOT needed for graphical applications.
+  tailored to the specific organization of pixels in the memory of
+  your graphics hardware. These are called the low level frame buffer
+  console drivers. Note that they are used for text console output
+  only; they are NOT needed for graphical applications.
 
   If you say N here, the needed low level drivers are automatically
   enabled, depending on what frame buffer devices you selected above.
@@ -1734,9 +1836,9 @@ CONFIG_FBCON_ADVANCED
   for color depths you do not intend to use for text consoles.
 
   Low level frame buffer console drivers can be modules ( = code which
-  can be inserted and removed from the running kernel whenever you want).
-  The modules will be called fbcon-*.o.  If you want to compile (some of)
-  them as modules, read Documentation/modules.txt.
+  can be inserted and removed from the running kernel whenever you
+  want). The modules will be called fbcon-*.o. If you want to compile
+  (some of) them as modules, read Documentation/modules.txt.
   
   If unsure, say N.
 
@@ -1747,23 +1849,24 @@ CONFIG_FBCON_MFB
 
 2 bpp packed pixels support
 CONFIG_FBCON_CFB2
-  This is the low level frame buffer console driver for 2 bits per pixel
-  (4 colors) packed pixels.
+  This is the low level frame buffer console driver for 2 bits per
+  pixel (4 colors) packed pixels.
 
 4 bpp packed pixels support
 CONFIG_FBCON_CFB4
-  This is the low level frame buffer console driver for 4 bits per pixel
-  (16 colors) packed pixels.
+  This is the low level frame buffer console driver for 4 bits per
+  pixel (16 colors) packed pixels.
 
 8 bpp packed pixels support
 CONFIG_FBCON_CFB8
-  This is the low level frame buffer console driver for 8 bits per pixel
-  (256 colors) packed pixels.
+  This is the low level frame buffer console driver for 8 bits per
+  pixel (256 colors) packed pixels.
 
 16 bpp packed pixels support
 CONFIG_FBCON_CFB16
   This is the low level frame buffer console driver for 15 or 16 bits
-  per pixel (32K or 64K colors, also known as `hicolor') packed pixels.
+  per pixel (32K or 64K colors, also known as `hicolor') packed
+  pixels.
 
 24 bpp packed pixels support
 CONFIG_FBCON_CFB24
@@ -1773,13 +1876,13 @@ CONFIG_FBCON_CFB24
 
 32 bpp packed pixels support
 CONFIG_FBCON_CFB32
-  This is the low level frame buffer console driver for 32 bits per pixel
-  (16M colors, also known as `truecolor') sparse packed pixels.
+  This is the low level frame buffer console driver for 32 bits per
+  pixel (16M colors, also known as `truecolor') sparse packed pixels.
 
 Amiga bitplanes support
 CONFIG_FBCON_AFB
-  This is the low level frame buffer console driver for 1 to 8 bitplanes
-  (2 to 256 colors) on Amiga.
+  This is the low level frame buffer console driver for 1 to 8
+  bitplanes (2 to 256 colors) on Amiga.
 
 Amiga interleaved bitplanes support
 CONFIG_FBCON_ILBM
@@ -1804,8 +1907,8 @@ CONFIG_FBCON_IPLAN2P8
 Mac variable bpp packed pixels support
 CONFIG_FBCON_MAC
   This is the low level frame buffer console driver for 1/2/4/8/16/32
-  bits per pixel packed pixels on Mac. It supports variable font widths
-  for low resolution screens.
+  bits per pixel packed pixels on Mac. It supports variable font
+  widths for low resolution screens.
   
 VGA characters/attributes support
 CONFIG_FBCON_VGA
@@ -1823,13 +1926,13 @@ CONFIG_PARPORT
 
   For extensive information about drivers for many devices attaching
   to the parallel port see http://www.torque.net/linux-pp.html on the
-  WWW (To browse the WWW, you need to have access to a machine on the
+  WWW (to browse the WWW, you need to have access to a machine on the
   Internet that has a program like lynx or netscape).
 
   It is possible to share a single parallel port among several devices
   and it is safe to compile all the corresponding drivers into the
-  kernel. If you want to compile parallel port support as a module 
-  ( = code which can be inserted in and removed from the running kernel
+  kernel. If you want to compile parallel port support 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.
   The module will be called parport.o. If you have more than one
   parallel port and want to specify which port and IRQ to be used by
@@ -1857,22 +1960,8 @@ CONFIG_PARPORT_OTHER
 Sun Ultra/AX-style hardware 
 CONFIG_PARPORT_AX
   Say Y here if you need support for the parallel port hardware on Sun
-  Ultra/AX machines.  This code is also available as a module (say M),
-  called parport_ax.o.  If in doubt, saying N is the safe plan.
-
-Generate little endian code
-CONFIG_CPU_LITTLE_ENDIAN
-  If your compiler is mipsel-linux-gcc or mipsel-linuxelf-gcc (as
-  opposed to mips-linux-gcc or mips-linuxelf-gcc), say Y here,
-  otherwise N. Most MIPS machines use little-endian code, but it might
-  be necessary to run older Mips systems, such as the Sony News and
-  MIPS RC3xxx, in big endian mode.
-
-Build fp execption handler module
-CONFIG_MIPS_FPE_MODULE
-  Build the floating point exception handler module.  This option is only
-  useful for people working on the floating point exception handler.  If
-  you don't, say n.
+  Ultra/AX machines. This code is also available as a module (say M),
+  called parport_ax.o. If in doubt, saying N is the safe plan.
 
 Plug and Play support
 CONFIG_PNP
@@ -1882,8 +1971,8 @@ CONFIG_PNP
 Auto-probe for parallel devices
 CONFIG_PNP_PARPORT
   Some IEEE-1284 conforming parallel-port devices can identify
-  themselves when requested.  Say Y to enable this feature, or M to
-  compile it as a module (parport_ieee1284.o).  If in doubt, say N.
+  themselves when requested. Say Y to enable this feature, or M to
+  compile it as a module (parport_ieee1284.o). If in doubt, say N.
 
 Enable loadable module support
 CONFIG_MODULES
@@ -1904,10 +1993,10 @@ CONFIG_MODVERSIONS
   same modules even after compiling a new kernel; this requires the
   program modprobe. All the software needed for module support is in
   the modutils package (check the file Documentation/Changes for
-  location and latest version).  NOTE: if you say Y here but don't
+  location and latest version). NOTE: if you say Y here but don't
   have the program genksyms (which is also contained in the above
   mentioned modutils package), then the building of your kernel will
-  fail.  If you are going to use modules that are generated from
+  fail. If you are going to use modules that are generated from
   non-kernel sources, you would benefit from this option. Otherwise
   it's not that important. So, N ought to be a safe bet.
 
@@ -1919,20 +2008,21 @@ CONFIG_KMOD
   modprobe) before you can use them. If you say Y here however, the
   kernel will be able to load modules for itself: when a part of the
   kernel needs a module, it runs modprobe with the appropriate
-  arguments. (This is a replacement for kerneld.) Say Y here and read
-  about configuring it in Documentation/kmod.txt.
+  arguments, thereby loading the module if it is available. (This is a
+  replacement for kerneld.) Say Y here and read about configuring it
+  in Documentation/kmod.txt.
 
 ARP daemon support (EXPERIMENTAL)
 CONFIG_ARPD
   Normally, the kernel maintains an internal cache which maps IP 
   addresses to hardware addresses on the local network, so that
   Ethernet/Token Ring/ etc. frames are sent to the proper address on
-  the physical networking layer.  For small networks having a few
+  the physical networking layer. For small networks having a few
   hundred directly connected hosts or less, keeping this address
-  resolution (ARP) cache inside the kernel works well.  However,
+  resolution (ARP) cache inside the kernel works well. However,
   maintaining an internal ARP cache does not work well for very large
   switched networks, and will use a lot of kernel memory if TCP/IP
-  connections are made to many machines on the network.  
+  connections are made to many machines on the network. 
 
   If you say Y here, the kernel's internal ARP cache will never grow
   to more than 256 entries (the oldest entries are expired in a LIFO
@@ -1940,10 +2030,10 @@ CONFIG_ARPD
   daemon arpd. Arpd then answers the address resolution request either
   from its own cache or by asking the net.
 
-  This code is still experimental. If you do say Y here, you should
-  obtain a copy of arpd from
-  http://www.loran.com/~layes/arpd/index.html, and you should also say
-  Y to "Kernel/User network link driver", below. If unsure, say N.
+  This code is experimental. If you do say Y here, you should obtain a
+  copy of arpd from http://www.loran.com/~layes/arpd/index.html, and
+  you should also say Y to "Kernel/User network link driver", below.
+  If unsure, say N.
 
 TCP/IP networking
 CONFIG_INET
@@ -1952,11 +2042,12 @@ CONFIG_INET
   kernel by about 35 kB), since some programs (e.g. the X window
   system) use TCP/IP even if your machine is not connected to any
   other computer. You will get the so-called loopback device which
-  allows you to ping yourself (great fun, that!). This option is also
-  necessary if you want to use the full power of 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 http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html).
+  allows you to ping yourself (great fun, that!). This option is 
+  also necessary if you want to use the full power of 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; for more information, read
+  http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html).
   
   If you say Y here and also to "/proc filesystem support" and "Sysctl
   support" below, you can change various aspects of the behavior of
@@ -1987,17 +2078,32 @@ CONFIG_IP_ADVANCED_ROUTER
   will then be presented with several options that allow more precise
   control about the routing process.
 
-  The answer to this question won't directly affect the kernel: saying
-  N will just cause this configure script to skip all the questions
-  about advanced routing.
+  The answer to this question won't directly affect the kernel:
+  answering N will just cause this configure script to skip all the
+  questions about advanced routing.
 
   Note that your box can only act as a router if you enable IP
   forwarding in your kernel; you can do that by saying Y to "/proc
-  filesystem support" and "Sysctl support" below and executing the line
+  filesystem support" and "Sysctl support" below and executing the
+  line
 
     echo "1" > /proc/sys/net/ipv4/ip_forward
 
-  at boot time after the /proc filesystem has been mounted.  
+  at boot time after the /proc filesystem has been mounted. 
+
+  If you turn on IP forwarding, you will also get the rp_filter, which
+  automatically rejects incoming packets if the routing table entry
+  for their source address doesn't match the network interface they're
+  arriving on. This has security advantages because it prevents the
+  so-called IP spoofing, however it can pose problems if you use
+  asymmetric routing (packets from you to a host take a different path
+  than packets from that host to you) or if you operate a non-routing
+  host which has several IP addresses on different interfaces. To turn
+  rp_filter off use:
+
+        echo 0 > /proc/sys/net/ipv4/conf/<device>/rp_filter
+  or
+        echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
 
   If unsure, say N here.
 
@@ -2005,8 +2111,10 @@ IP: policy routing
 CONFIG_IP_MULTIPLE_TABLES
   Normally, a router decides what to do with a received packet based
   solely on the packet's final destination address. If you say Y here,
-  routing can also take into account the originating address and the
-  network device from which the packet reached us.
+  the Linux router will also be able to take the packet's source
+  address into account. Furthermore, if you also say Y to "IP: use TOS
+  value as routing key" below, the TOS (Type-Of-Service) field of the
+  packet can be used for routing decisions as well.
 
 IP: equal cost multipath
 CONFIG_IP_ROUTE_MULTIPATH
@@ -2022,10 +2130,9 @@ IP: use TOS value as routing key
 CONFIG_IP_ROUTE_TOS
   The header of every IP packet carries a TOS (Type of Service) value
   with which the packet requests a certain treatment, e.g. low latency
-  (for interactive traffic), high throughput, or high reliability.
-  Normally, these values are ignored, but if you say Y here, you will
-  be able to specify different routes for packets with different TOS
-  values.
+  (for interactive traffic), high throughput, or high reliability. If
+  you say Y here, you will be able to specify different routes for
+  packets with different TOS values.
 
 IP: verbose route monitoring
 CONFIG_IP_ROUTE_VERBOSE
@@ -2044,7 +2151,8 @@ CONFIG_IP_ROUTE_LARGE_TABLES
 IP: fast network address translation
 CONFIG_IP_ROUTE_NAT
   If you say Y here, your router will be able to modify source and
-  destination addresses of packets that pass through it.
+  destination addresses of packets that pass through it, in a manner
+  you specify.
 
 IP: optimize as router not host
 CONFIG_IP_ROUTER
@@ -2057,11 +2165,13 @@ CONFIG_IP_ROUTER
 
   Note that your box can only act as a router if you enable IP
   forwarding in your kernel; you can do that by saying Y to "/proc
-  filesystem support" and "Sysctl support" below and executing the line
+  filesystem support" and "Sysctl support" below and executing the
+  line
 
     echo "1" > /proc/sys/net/ipv4/ip_forward
 
-  at boot time after the /proc filesystem has been mounted.  
+  at boot time after the /proc filesystem has been mounted. You can do
+  that even if you say N here.
 
   If unsure, say N here.
 
@@ -2095,7 +2205,7 @@ CONFIG_IP_FIREWALL
 
     echo "1" > /proc/sys/net/ipv4/ip_forward
 
-  at boot time after the /proc filesystem has been mounted.  
+  at boot time after the /proc filesystem has been mounted. 
 
   You need to say Y to "IP firewalling" in order to be able to use IP
   masquerading (masquerading means that local computers can chat with
@@ -2131,10 +2241,10 @@ CONFIG_IP_PNP
   This enables automatic configuration of IP addresses of devices and
   of the routing table during kernel boot, based on either information
   supplied at the kernel command line or by BOOTP or RARP protocols.
-  You need to say Y only for diskless machines requiring network access
-  to boot (in which case you want to say Y to "Root file system on
-  NFS" as well), because all other machines configure the network in
-  their startup scripts.
+  You need to say Y only for diskless machines requiring network
+  access to boot (in which case you want to say Y to "Root file system
+  on NFS" as well), because all other machines configure the network
+  in their startup scripts.
 
 BOOTP support
 CONFIG_IP_PNP_BOOTP
@@ -2144,7 +2254,7 @@ CONFIG_IP_PNP_BOOTP
   the BOOTP protocol (a special protocol designed for doing this job),
   say Y here. In case the boot ROM of your network card was designed
   for booting Linux and does BOOTP itself, providing all necessary
-  information on the kernel command line, you can say N here.  If
+  information on the kernel command line, you can say N here. If
   unsure, say Y. Note that if you want to use BOOTP, a BOOTP server
   must be operating on your network. Read Documentation/nfsroot.txt
   for details.
@@ -2201,7 +2311,7 @@ CONFIG_IP_TRANSPARENT_PROXY
   This enables your Linux firewall to transparently redirect any
   network traffic originating from the local network and destined
   for a remote host to a local server, called a "transparent proxy
-  server".  This makes the local computers think they are talking to
+  server". This makes the local computers think they are talking to
   the remote end, while in fact they are connected to the local
   proxy. Redirection is activated by defining special input firewall
   rules (using the ipchains utility) and/or by doing an appropriate
@@ -2233,7 +2343,7 @@ CONFIG_IP_MASQUERADE
 
     echo "1" > /proc/sys/net/ipv4/ip_forward
 
-  from a boot time script after the /proc filesystem has been mounted. 
+  from a boot time script after the /proc filesystem has been mounted.
 
   Details on how to set things up are contained in the IP Masquerade
   mini-HOWTO, available via FTP (user: anonymous) from
@@ -2244,33 +2354,55 @@ CONFIG_IP_MASQUERADE
   If you say Y here, you should also say Y to "IP: always defragment",
   below. 
 
-  If you say Y here, then the modules ip_masq_ftp.o (for ftp transfers
-  through the firewall), ip_masq_irc.o (for irc chats through the
-  firewall), and ip_masq_raudio.o (for RealAudio downloads through the
-  firewall) will automatically be compiled. Modules are pieces of code
-  which can be inserted in and removed from the running kernel
-  whenever you want; read Documentation/modules.txt for details.
+  If you say Y here, then the modules ip_masq_ftp.o (for ftp file
+  transfers), ip_masq_irc.o (for irc chats), ip_masq_quake.o (you
+  guessed it), ip_masq_vdolive.o (for VDOLive video connections),
+  ip_masq_cuseeme.o (for CU-SeeMe broadcasts) and ip_masq_raudio.o
+  (for RealAudio downloads) will automatically be compiled. They are
+  needed to make masquerading for these protocols work. Modules are
+  pieces of code which can be inserted in and removed from the running
+  kernel whenever you want; read Documentation/modules.txt for
+  details.
 
 IP: ICMP masquerading
 CONFIG_IP_MASQUERADE_ICMP
-  The basic masquerade code described for "IP: masquerading" above only
-  handles TCP or UDP packets (and ICMP errors for existing 
-  connections).  This option adds additional support for masquerading
+  The basic masquerade code described for "IP: masquerading" above
+  only handles TCP or UDP packets (and ICMP errors for existing
+  connections). This option adds additional support for masquerading
   ICMP packets, such as ping or the probes used by the Windows 95
   tracert program.
 
   If you want this, say Y. 
 
+IP: masquerading special modules support
+CONFIG_IP_MASQUERADE_MOD
+  This provides support for special modules that can modify the
+  rewriting rules used when masquerading. Please not that this feature
+  adds a little overhead in the input packet processing chain.
+
+  Examples of such modules are ipautofw (allowing the masquerading of
+  protocols which don't have their own protocol helpers) and port
+  forwarding (making an incoming port of a local computer visible
+  through the masquerading host).
+
+  You will need the user space program "ipmasqadm" to use these
+  additional modules; you can download it from
+  http://juanjox.home.ml.org/
+
+  All this additional code is still under development and so is
+  currently marked EXPERIMENTAL.
+  
+  If you want to try, for example, PORT FORWARDING, say Y.
+
 IP: ipautofw masquerade support (Experimental)
 CONFIG_IP_MASQUERADE_IPAUTOFW
-  ipautofw is a program by Richard Lynch allowing additional support
-  for masquerading protocols which do not (as yet) have their own
-  protocol helpers. Information and source for ipautofw is available
-  via FTP (user: anonymous) from
+  ipautofw is a program which allows the masquerading of protocols
+  which do not (as yet) have their own protocol helpers. Information
+  and source for ipautofw is available via FTP (user: anonymous) from
   ftp://ftp.netis.com/pub/members/rlynch/
 
-  For 2.1 kernels, you will need "ipmasqadm" tool from
-  http://juanjox.home.ml.org
+  You will also need the ipmasqadm tool available from
+  http://juanjox.home.ml.org .
 
   The ipautofw code is still under development and so is currently
   marked EXPERIMENTAL. If you want to try it, say Y.
@@ -2280,44 +2412,27 @@ CONFIG_IP_MASQUERADE_IPAUTOFW
   The module will be called ip_masq_autofw.o. If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
-IP: masquerading special modules support
-CONFIG_IP_MASQUERADE_MOD
-  This provides support for special modules that can modify rewriting
-  rules to achieve, for example, input port forwarding.
-  Beware that this feature adds a little overhead in the input packet
-  processing chain.
-
-  You will need user space program "ipmasqadm" to use these
-  additional modules, you can download it from 
-  http://juanjox.home.ml.org/
-
-  All this additional code is still under development and so is currently
-  marked EXPERIMENTAL. 
-  
-  If you want to try, for example, PORT FORWARDING, say Y.
-
 IP: ipportfw masquerade support
 CONFIG_IP_MASQUERADE_IPPORTFW
-  Port Forwarding is an addition to IP Masquerading written by Steven
-  Clarke to allow some forwarding of packets from outside to inside a
-  firewall on given ports. This could be useful if, for example, you
-  want to run a web server behind the firewall or masquerading host
-  and this web server should be visible to the outside world. An
-  external client connects to port 80 of the firewall, the firewall
-  forwards requests to this port to the web server, the web server
-  handles the request and the results are sent through the firewall to
-  the original client. The client thinks that the firewall machine
-  itself is running the web server.
+  Port Forwarding is an addition to IP Masquerading which allows some
+  forwarding of packets from outside to inside a firewall on given
+  ports. This could be useful if, for example, you want to run a web
+  server behind the firewall or masquerading host and this web server
+  should be visible to the outside world. An external client connects
+  to port 80 of the firewall, the firewall forwards requests to this
+  port to the web server, the web server handles the request and the
+  results are sent through the firewall to the original client. The
+  client thinks that the firewall machine itself is running the web
+  server.
 
   Information about it is available from
   http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html (to
   browse the WWW, you need to have access to a machine on the Internet
-  that has a program like lynx or netscape). You will need the user
-  space program "ipmasqadm" which can be downloaded from
-  http://juanjox.home.ml.org/
+  that has a program like lynx or netscape). For general info, please
+  see ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/
 
-  For general info, please see
-  ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/
+  You will need the user space program "ipmasqadm" which can be
+  downloaded from http://juanjox.home.ml.org/
 
   The portfw code is still under development and so is currently
   marked EXPERIMENTAL. If you want to try it, say Y.
@@ -2329,9 +2444,9 @@ CONFIG_IP_MASQUERADE_IPPORTFW
 
 IP: ipmarkfw masquerade support
 CONFIG_IP_MASQUERADE_IPMARKFW
-  This provides functionally equivalent to port forwarding, the difference
-  is that Mark Forwarding uses "firewalling mark" to select which packets
-  must forward (see ipchains(8), "-m" argument).
+  This provides functionality equivalent to port forwarding, the
+  difference is that Mark Forwarding uses "firewalling mark" to select
+  which packets must forward (see ipchains(8), "-m" argument).
 
   The markfw code is still under development and so is currently
   marked EXPERIMENTAL. If you want to try it, say Y.
@@ -2343,37 +2458,41 @@ CONFIG_IP_MASQUERADE_IPMARKFW
 
 IP: always defragment 
 CONFIG_IP_ALWAYS_DEFRAG
-  This option means that all incoming fragments (= parts of IP packets
+  If you say Y here, then all incoming fragments (parts of IP packets
   that arose when some host between origin and destination decided
-  that the IP packets were too large and cut them into pieces) will be
+  that the packets were too large and cut them into pieces) will be
   reassembled (defragmented) before being processed, even if they are
-  about to be forwarded.  
+  about to be forwarded.
 
   This option is highly recommended if you have said Y to "IP:
   masquerading" because that facility requires that second and further
   fragments can be related to TCP or UDP port numbers, which are only
-  stored in the first fragment. When using "IP: firewalling" support ,
-  you might also want to say Y here, to have a more reliable firewall
-  (otherwise second and further fragments will always be accepted by
-  the firewall). When using "IP: transparent proxying", this option is
-  implicit, although it is safe to say Y here. Only say Y here if
-  running either a firewall that is the sole link to your network or a
-  transparent proxy; never ever say Y here for a normal router or
-  host.
+  stored in the first fragment.
+
+  When using "IP: firewalling" support, you might also want to say Y
+  here, to have a more reliable firewall (otherwise second and further
+  fragments must be dealt with by the firewall, which can be tricky).
+
+  When using "IP: transparent proxying", this option is implicit,
+  although it is safe to say Y here.
+
+  Only say Y here if running either a firewall that is the sole link
+  to your network or a transparent proxy; never ever say Y here for a
+  normal router or host.
 
 IP: aliasing support
 CONFIG_IP_ALIAS
   Sometimes it is useful to give several IP addresses to a single
-  physical network interface (= serial port or Ethernet card). The
-  most common case is that you want to serve different WWW or ftp
-  documents to the outside according to which of your host names was
-  used to connect to you. This is called "multihosting" or "virtual
-  domains" or "virtual hosting services" and is explained in detail on
-  the WWW at http://www.thesphere.com/~dlp/TwoServers/ (to browse the
-  WWW, you need to have access to a machine on the Internet that has a
-  program like lynx or netscape) and also in the
-  Virtual-Hosting-HOWTO, available via FTP (user: anonymous) from
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
+  physical network interface (serial port or Ethernet card). The most
+  common case is that you want to serve different WWW or ftp documents
+  to the outside according to which of your host names was used to
+  connect to you. This is called "multihosting" or "virtual domains"
+  or "virtual hosting services" and is explained in detail on the WWW
+  at http://www.thesphere.com/~dlp/TwoServers/ (to browse the WWW, you
+  need to have access to a machine on the Internet that has a program
+  like lynx or netscape) and also in the Virtual-Hosting-HOWTO,
+  available via FTP (user: anonymous) from
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
 
   Another scenario would be
   that there are two logical networks living on your local Ethernet
@@ -2400,27 +2519,31 @@ IP: PIM-SM version 1 support
 CONFIG_IP_PIMSM_V1
   Kernel side support for Sparse Mode PIM (Protocol Independent
   Multicast) version 1. This multicast routing protocol is used widely
-  because Cisco supports it.  You need special software to use it
+  because Cisco supports it. You need special software to use it
   (pimd-v1). Please see http://netweb.usc.edu/pim/ for more
   information about PIM (to browse the WWW, you need to have access to
   a machine on the Internet that has a program like lynx or
-  netscape). Say Y if you want to use PIM-SM v1. Note that you can say
-  N here if you just want to use Dense Mode PIM.
+  netscape). 
+
+  Say Y if you want to use PIM-SM v1. Note that you can say N here if
+  you just want to use Dense Mode PIM.
 
 IP: PIM-SM version 2 support
 CONFIG_IP_PIMSM_V2
   Kernel side support for Sparse Mode PIM version 2. In order to use
   this, you need an experimental routing daemon supporting it (pimd or
-  gated-5).  This routing protocol is not used widely, so say N unless
+  gated-5). This routing protocol is not used widely, so say N unless
   you want to play with it.
 
 PC/TCP compatibility mode
 CONFIG_INET_PCTCP
-  If you have been having difficulties telnetting to your Linux machine
-  from a DOS system that uses (broken) PC/TCP networking software (all
-  versions up to OnNet 2.0) over your local Ethernet try saying Y
-  here.  Everyone else says N. People having problems with NCSA telnet
-  should see the file linux/Documentation/networking/ncsa-telnet.
+  If you have been having difficulties telnetting to your Linux
+  machine from a DOS system that uses (broken) PC/TCP networking
+  software (all versions up to OnNet 2.0) over your local Ethernet try
+  saying Y here. Everyone else says N. 
+
+  People having problems with NCSA telnet should see the file
+  linux/Documentation/networking/ncsa-telnet.
 
 Reverse ARP server
 CONFIG_INET_RARP
@@ -2431,9 +2554,9 @@ CONFIG_INET_RARP
   addresses. Diskless Sun 3 machines use this procedure at boot time,
   and diskless Linux boxes can be configured to do it as well.
   
-  If you want your Linux box to be able to *answer* such requests, say
-  Y here; you'll then have to run the program rarp ("man rarp") on
-  your box.
+  If you want your Linux box to be able to *answer* such requests,
+  answer Y here; you'll then have to run the program rarp ("man rarp")
+  on your box.
 
   If you actually want to use a diskless Sun 3 machine as an X
   terminal to Linux, say Y here and fetch Linux-Xkernel from
@@ -2459,8 +2582,9 @@ CONFIG_INET_SNARL
   Say Y if you are on a subnetted network with all machines connected
   by Ethernet segments only, as this option optimizes network access
   for this special case. If there are other connections, e.g. SLIP
-  links, between machines of your IP network, say N.  If in doubt, say
-  N. The PATH mtu discovery facility will cover most cases anyway.
+  links, between machines of your IP network, say N. If in doubt,
+  answer N. The PATH mtu discovery facility will cover most cases
+  anyway.
 
 Path MTU Discovery (normally enabled)
 CONFIG_PATH_MTU_DISCOVERY
@@ -2468,8 +2592,8 @@ CONFIG_PATH_MTU_DISCOVERY
   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 most people say
-  Y here. 
+  we adjust to a smaller size. This is good, so most people say Y
+  here.
 
   However, some DOS software (versions of DOS NCSA telnet and Trumpet
   Winsock in PPP mode) is broken and won't be able to connect to your
@@ -2481,37 +2605,39 @@ CONFIG_PATH_MTU_DISCOVERY
 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 telnet and
-  rlogin packets from congesting Wide Area Networks.  Most people
+  sending small IP frames (packets). This keeps tiny telnet and
+  rlogin packets from congesting Wide Area Networks. Most people
   strongly recommend to say N here, thereby leaving NAGLE
   enabled. Those programs that would benefit from disabling this
   facility can do it on a per connection basis themselves.
 
 IP: Drop source routed frames
 CONFIG_IP_NOSR
-  Usually, the originator of an IP frame (packet) specifies only the
+  Usually, the originator of an IP frame (packet) specifies only the
   destination, and the hosts along the way do the routing, i.e. they
   decide how to forward the frame. However, there is a feature of the
   IP protocol that allows to specify the full route for a given frame
   already at its origin. A frame with such a fully specified route is
   called "source routed". The question now is whether we should honour
-  these route requests when such frames arrive, or if we should
-  drop all those frames instead. Honouring them can introduce security
-  problems (and is rarely a useful feature), and hence it is recommended
-  that you say Y here unless you really know what you're doing.
+  these route requests when such frames arrive, or if we should drop
+  all those frames instead. Honouring them can introduce security
+  problems (and is rarely a useful feature), and hence it is
+  recommended that you say Y here unless you really know what you're
+  doing.
 
-IP: Allow large windows (not recommended if <16Mb of memory)
+IP: Allow large windows (not recommended if <16 MB of memory)
 CONFIG_SKB_LARGE
   On high speed, long distance networks the performance limit on
-  networking becomes the amount of data a machine can buffer until the
-  other end confirms its reception. (At 45Mbit/second there are a lot
-  of bits between New York and London ...). This option allows larger
-  amounts of data to be "in flight" at a given time. It also means a
-  user process can require a lot more memory for network buffers and
-  thus this option is best used only on machines with 16Mb of memory
-  or higher. Unless you are using long links with end to end speeds of
-  over 2Mbit a second or satellite links this option will make no
-  difference to performance.
+  networking becomes the amount of data the sending machine can buffer
+  until the other end confirms its reception. (At 45 Mbit/second there
+  are a lot of bits between New York and London ...). If you say Y
+  here, bigger buffers can be used which allows larger amounts of data
+  to be "in flight" at any given time. It also means a user process
+  can require a lot more memory for network buffers and thus this
+  option is best used only on machines with 16 MB of memory or higher.
+  Unless you are using long links with end to end speeds of over 2
+  Mbit a second or satellite links this option will make no difference
+  to performance.
 
 Unix domain sockets
 CONFIG_UNIX
@@ -2549,6 +2675,11 @@ CONFIG_IPV6
   given in Documentation/Changes. You will still be able to do regular
   IPv4 networking as well.
 
+  This protocol support is also available as a module ( = code which
+  can be inserted in and removed from the running kernel whenever you
+  want). The module will be called ipv6.o. If you want to compile it
+  as a module, say M here and read Documentation/modules.txt.
+
   It is safe to say N here for now.
 
 IPv6: enable EUI-64 token format
@@ -2612,12 +2743,12 @@ IPX: Full internal IPX network
 CONFIG_IPX_INTERN
   Every IPX network has an address that identifies it. Sometimes it is
   useful to give an IPX "network" address to your Linux box as well
-  (for example if your box is acting as a file server for different IPX
-  networks: it will then be accessible from everywhere using the same
-  address).  The way this is done is to create a virtual internal
+  (for example if your box is acting as a file server for different
+  IPX networks: it will then be accessible from everywhere using the
+  same address). The way this is done is to create a virtual internal
   "network" inside your box and to assign an IPX address to this
   network. Say Y here if you want to do this; read the IPX-HOWTO at
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO for details.  
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO for details.
 
   The full internal IPX network enables you to allocate sockets on
   different virtual nodes of the internal network. This is done by
@@ -2625,13 +2756,14 @@ CONFIG_IPX_INTERN
   bind call. So applications should always initialize the node field
   to 0 when binding a socket on the primary network. In this case the
   socket is assigned the default node that has been given to the
-  kernel when the internal network was created.  By enabling the full
+  kernel when the internal network was created. By enabling the full
   internal IPX network the cross-forwarding of packets targeted at
   'special' sockets to sockets listening on the primary network is
   disabled. This might break existing applications, especially RIP/SAP
   daemons. A RIP/SAP daemon that works well with the full internal net
-  can be found on ftp://ftp.gwdg.de/pub/linux/misc/ncpfs.  If you don't
-  know what you are doing, say N.
+  can be found on ftp://ftp.gwdg.de/pub/linux/misc/ncpfs. 
+
+  If you don't know what you are doing, say N.
 
 IPX: SPX networking (EXPERIMENTAL)
 CONFIG_SPX
@@ -2683,7 +2815,7 @@ CONFIG_ATALK
 AppleTalk-IP driver support
 CONFIG_IPDDP
   This allows IP networking for users who only have AppleTalk
-  networking available.  This feature is experimental. With this
+  networking available. This feature is experimental. With this
   driver, you can either encapsulate IP inside AppleTalk (e.g. if your
   Linux box is stuck on an AppleTalk only network) or decapsulate
   (e.g. if you want your Linux box to act as an Internet gateway for a
@@ -2718,7 +2850,7 @@ CONFIG_IPDDP_DECAP
 Apple/Farallon LocalTalk PC card support
 CONFIG_LTPC
   This allows you to use the AppleTalk PC card to connect to LocalTalk
-  networks.  The card is also known as the Farallon PhoneNet PC card.
+  networks. The card is also known as the Farallon PhoneNet PC card.
   If you are in doubt, this card is the one with the 65C02 chip on it.
   You also need version 1.3.3 or later of the netatalk package.
   This driver is experimental, which means that it may not work.
@@ -2728,8 +2860,8 @@ COPS LocalTalk PC card support
 CONFIG_COPS
   This allows you to use COPS AppleTalk cards to connect to LocalTalk
   networks. You also need version 1.3.3 or later of the netatalk
-  package.  This driver is experimental, which means that it may not
-  work.  This driver will only work if you choose "AppleTalk DDP"
+  package. This driver is experimental, which means that it may not
+  work. This driver will only work if you choose "AppleTalk DDP"
   networking support, above.
   Please read the file Documentation/networking/cops.txt. 
 
@@ -2746,15 +2878,16 @@ CONFIG_COPS_TANGENT
 
 Amateur Radio support
 CONFIG_HAMRADIO
-  If you want to connect your Linux computer to an amateur radio, say
-  here. You want to read http://www.tapr.org/tapr/html/pkthome.html
+  If you want to connect your Linux box to an amateur radio, answer Y
+  here. You want to read http://www.tapr.org/tapr/html/pkthome.html
   (to browse the WWW, you need to have access to a machine on the
   Internet that has a program like lynx or netscape) and the HAM-HOWTO
   and the AX25-HOWTO, both available via FTP (user: anonymous) from
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that the answer to
-  this question won't directly affect the kernel: saying N will just
-  cause this configure script to skip all the questions about amateur
-  radio.
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+  Note that the answer to this question won't directly affect the
+  kernel: saying N will just cause this configure script to skip all
+  the questions about amateur radio.
 
 Amateur Radio AX.25 Level 2
 CONFIG_AX25
@@ -2815,7 +2948,7 @@ CONFIG_NETROM
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. You also might want to
   check out the file Documentation/networking/ax25.txt. More
   information about digital amateur radio in general is on the WWW at
-  http://www.tapr.org/tapr/html/pkthome.html (To browse the WWW, you
+  http://www.tapr.org/tapr/html/pkthome.html (to browse the WWW, you
   need to have access to a machine on the Internet that has a program
   like lynx or netscape).
 
@@ -2836,7 +2969,7 @@ CONFIG_ROSE
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. You also might want to
   check out the file Documentation/networking/ax25.txt. More
   information about digital amateur radio in general is on the WWW at
-  http://www.tapr.org/tapr/html/pkthome.html (To browse the WWW, you
+  http://www.tapr.org/tapr/html/pkthome.html (to browse the WWW, you
   need to have access to a machine on the Internet that has a program
   like lynx or netscape).
 
@@ -2849,7 +2982,10 @@ Serial port KISS driver for AX.25
 CONFIG_MKISS
   KISS is a protocol used for the exchange of data between a computer
   and a Terminal Node Controller (a small embedded system commonly
-  used for networking over AX25 amateur radio connections).
+  used for networking over AX.25 amateur radio connections; it
+  connects the computer's serial port with the radio's microphone
+  input and speaker output).
+
   Although KISS is less advanced than the 6pack protocol, it has
   the advantage that it is already supported by most modern TNCs
   without the need for a firmware upgrade.
@@ -2900,15 +3036,15 @@ CONFIG_DMASCC
   the AX25-HOWTO, available via FTP (user: anonymous) in
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/.
 
-  This driver can operate multiple boards simultaneously. If you compile
-  it as a module (by saying M instead of Y), it will be called dmascc.o.
-  If you don't pass any parameter to the driver, all possible I/O
-  addresses are probed. This could irritate other devices that are
-  currently not in use. You may specify the list of addresses to be
-  probed by "dmascc=addr1,addr2,..." (when compiled into the kernel
-  image) or "io=addr1,addr2,..." (when loaded as a module). The network
-  interfaces will be called dmascc0 and dmascc1 for the board detected
-  first, dmascc2 and dmascc3 for the second one, and so on. 
+  This driver can operate multiple boards simultaneously. If you
+  compile it as a module (by saying M instead of Y), it will be called
+  dmascc.o. If you don't pass any parameter to the driver, all
+  possible I/O addresses are probed. This could irritate other devices
+  that are currently not in use. You may specify the list of addresses
+  to be probed by "dmascc=addr1,addr2,..." (when compiled into the
+  kernel image) or "io=addr1,addr2,..." (when loaded as a module). The
+  network interfaces will be called dmascc0 and dmascc1 for the board
+  detected first, dmascc2 and dmascc3 for the second one, and so on.
 
   Before you configure each interface with ifconfig, you MUST set
   certain parameters, such as channel access timing, clock mode, and
@@ -2984,7 +3120,7 @@ CONFIG_BAYCOM_SER_FDX
   driver, "BAYCOM ser12 half duplex driver for AX.25" is the old
   driver and still provided in case this driver does not work with
   your serial interface chip. To configure the driver, use the sethdlc
-  utility available in the standard ax25 utilities package.  For
+  utility available in the standard ax25 utilities package. For
   information on the modems, see http://www.baycom.de (to browse the
   WWW, you need to have access to a machine on the Internet that has a
   program like lynx or netscape) and
@@ -2999,9 +3135,9 @@ BAYCOM ser12 half duplex driver for AX.25
 CONFIG_BAYCOM_SER_HDX
   This is one of two drivers for Baycom style simple amateur radio
   modems that connect to a serial interface. The driver supports the
-  ser12 design in full duplex mode. This is the old driver.  It is
+  ser12 design in full duplex mode. This is the old driver. It is
   still provided in case your serial interface chip does not work with
-  the full duplex driver. This driver is depreciated.  To configure
+  the full duplex driver. This driver is depreciated. To configure
   the driver, use the sethdlc utility available in the standard ax25
   utilities package. For information on the modems, see
   http://www.baycom.de (to browse the WWW, you need to have access to
@@ -3016,9 +3152,9 @@ CONFIG_BAYCOM_SER_HDX
 Sound card modem driver for AX.25
 CONFIG_SOUNDMODEM
   This experimental driver allows a standard Sound Blaster or
-  WindowsSoundSystem compatible sound card to be used as a packet radio
-  modem (NOT as a telephone modem!), to send digital traffic over
-  amateur radio. 
+  WindowsSoundSystem compatible sound card to be used as a packet
+  radio modem (NOT as a telephone modem!), to send digital traffic
+  over amateur radio.
 
   To configure the driver, use the sethdlc, smdiag and smmixer
   utilities available in the standard ax25 utilities package. For
@@ -3039,8 +3175,8 @@ CONFIG_SOUNDMODEM_SBC
   compatible cards. If you have a dual mode card (i.e. a WSS cards
   with a Sound Blaster emulation) you should say N here and Y to
   "Sound card modem support for WSS and Crystal cards", below, because
-  this usually results in better performance. This option also supports
-  SB16/32/64 in full duplex mode.
+  this usually results in better performance. This option also
+  supports SB16/32/64 in full duplex mode.
 
 Sound card modem support for WSS and Crystal cards
 CONFIG_SOUNDMODEM_WSS
@@ -3054,15 +3190,16 @@ CONFIG_SOUNDMODEM_WSS
 
 Sound card modem support for 1200 baud AFSK modulation
 CONFIG_SOUNDMODEM_AFSK1200
-  This option enables the soundmodem driver 1200 baud AFSK modem, 
-  compatible to popular modems using TCM3105 or AM7911. The demodulator
-  requires about 12% of the CPU power of a Pentium 75 CPU per channel.
+  This option enables the soundmodem driver 1200 baud AFSK modem,
+  compatible to popular modems using TCM3105 or AM7911. The
+  demodulator requires about 12% of the CPU power of a Pentium 75 CPU
+  per channel.
 
 Sound card modem support for 2400 baud AFSK modulation (7.3728MHz crystal)
 CONFIG_SOUNDMODEM_AFSK2400_7
   This option enables the soundmodem driver 2400 baud AFSK modem,
   compatible to TCM3105 modems (over-)clocked with a 7.3728MHz
-  crystal.  Note that the availability of this driver does _not_ imply
+  crystal. Note that the availability of this driver does _not_ imply
   that I recommend building such links. It is only here since users
   especially in eastern Europe have asked me to do so. In fact this
   modulation scheme has many disadvantages, mainly its incompatibility
@@ -3097,7 +3234,7 @@ CONFIG_SOUNDMODEM_HAPN4800
   This option enables the soundmodem driver 4800 baud HAPN-1
   compatible modem. This modulation seems to be widely used 'down
   under' and in the Netherlands. Here, nobody uses it, so I could not
-  test if it works.  It is compatible to itself, however :-)
+  test if it works. It is compatible to itself, however :-)
 
 Sound card modem support for 9600 baud FSK G3RUH modulation
 CONFIG_SOUNDMODEM_FSK9600
@@ -3116,7 +3253,7 @@ CONFIG_X25
   (called "virtual circuits") to other computers connected to the X.25
   network. Governments, banks, and other organizations tend to use it
   to connect to each other or to form Wide Area Networks (WANs). Many
-  countries have public X.25 networks.  X.25 consists of two
+  countries have public X.25 networks. X.25 consists of two
   protocols: the higher level Packet Layer Protocol (PLP) (say Y here
   if you want that) and the lower level data link layer protocol LAPB
   (say Y to "LAPB Data Link Driver" below if you want that). 
@@ -3144,16 +3281,16 @@ CONFIG_X25
 
 LAPB Data Link Driver (EXPERIMENTAL) 
 CONFIG_LAPB
-  Link Access Procedure, Balanced (LAPB) is the data link layer
-  (i.e. the lower) part of the X.25 protocol. It offers a reliable
+  Link Access Procedure, Balanced (LAPB) is the data link layer (i.e.
+  the lower) part of the X.25 protocol. It offers a reliable
   connection service to exchange data frames with one other host, and
   it is used to transport higher level protocols (mostly X.25 Packet
-  Layer, the higher part of X.25, but others are possible as
-  well). Usually, LAPB is used with specialized X.21 network cards, but
-  Linux currently supports LAPB only over Ethernet connections. If you
-  want to use LAPB connections over Ethernet, say Y here and to "LAPB
-  over Ethernet driver" below.  Read
-  Documentation/networking/lapb-module.txt for technical details.  
+  Layer, the higher part of X.25, but others are possible as well).
+  Usually, LAPB is used with specialized X.21 network cards, but Linux
+  currently supports LAPB only over Ethernet connections. If you want
+  to use LAPB connections over Ethernet, say Y here and to "LAPB over
+  Ethernet driver" below. Read
+  Documentation/networking/lapb-module.txt for technical details.
 
   If you want to compile this driver as a module though ( = code which
   can be inserted in and removed from the running kernel whenever you
@@ -3225,16 +3362,6 @@ CONFIG_NETLINK_DEV
   This is a backward compatibility option, choose Y for now.
   This option will be removed soon.
 
-HIgh Performance Parallel Interface support (EXPERIMENTAL)
-CONFIG_HIPPI
-  HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
-  1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
-  can run over copper (25m) or fiber (300m on multi-mode or 10km on
-  single-mode). If you are connected to a HIPPI network, and want
-  to enable HIPPI support in the kernel, say Y here (you must also
-  remember to enable the driver for your HIPPI card below). Most
-  people will say N here.
-
 SCSI support?
 CONFIG_SCSI
   If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or
@@ -3244,10 +3371,13 @@ CONFIG_SCSI
   because you will be asked for it. 
 
   You also need to say Y here if you want support for the parallel
-  port version of the 100MB IOMEGA ZIP drive.
+  port version of the 100 MB IOMEGA ZIP drive.
 
   Please read the SCSI-HOWTO, available via FTP (user: anonymous) in
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. The
+  SCSI-Programming-HOWTO contains information about how to add or
+  remove an SCSI device from a running Linux machine without
+  rebooting. 
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -3261,9 +3391,9 @@ SCSI disk support
 CONFIG_BLK_DEV_SD
   If you want to use a SCSI hard disk or the SCSI or parallel port
   version of the IOMEGA ZIP drive under Linux, say Y and read the
-  SCSI-HOWTO and the Disk-HOWTO, both available via FTP (user:
-  anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This is
-  NOT for SCSI CDROMs.
+  SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available via
+  FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+  This is NOT for SCSI CDROMs.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -3292,8 +3422,8 @@ SCSI CDROM support
 CONFIG_BLK_DEV_SR
   If you want to use a SCSI CDROM under Linux, say Y and read the
   SCSI-HOWTO and the CDROM-HOWTO from
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also make sure to say Y or M 
-  to "ISO 9660 CDROM filesystem support" later. 
+  ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also make sure to say Y
+  or M to "ISO 9660 CDROM filesystem support" later.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -3316,11 +3446,11 @@ CONFIG_CHR_DEV_SG
   directly, so you need some additional software which knows how to
   talk to these devices using the SCSI protocol. For CD-writers, you
   would need the program cdwrite, available via FTP (user: anonymous)
-  from ftp://sunsite.unc.edu/pub/Linux/utils/disk-management; for other
-  devices, it's possible that you'll have to write the driver software
-  yourself, so have a look at the SCSI-HOWTO and at the
+  from ftp://sunsite.unc.edu/pub/Linux/utils/disk-management; for
+  other devices, it's possible that you'll have to write the driver
+  software yourself, so have a look at the SCSI-HOWTO and at the
   SCSI-Programming-HOWTO, both available via FTP (user: anonymous) in
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO. 
+  ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO.
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -3334,7 +3464,7 @@ CONFIG_SCSI_MULTI_LUN
   Unit Number), e.g. a CD jukebox, and only one LUN is detected, you
   can say Y here to force the SCSI driver to probe for multiple LUNs. 
   A SCSI device with multiple LUNs acts logically like multiple SCSI
-  devices.  The vast majority of SCSI devices have only one LUN, and
+  devices. The vast majority of SCSI devices have only one LUN, and
   so most people can say N here and should in fact do so, because it
   is safer.
 
@@ -3342,24 +3472,30 @@ Verbose SCSI error reporting (kernel size +=12K)
 CONFIG_SCSI_CONSTANTS
   The error messages regarding your SCSI hardware will be easier to
   understand if you say Y here; it will enlarge your kernel by about
-  12KB. If in doubt, say Y.
+  12 KB. If in doubt, say Y.
 
 SCSI logging facility
 CONFIG_SCSI_LOGGING
   This turns on a logging facility that can be used to debug a number
-  of problems.  Normally no logging output will appear, but you can
-  enable logging with a shell command like: 
+  of SCSI related problems. 
+
+  If you say Y here, no logging output will appear by default, but you
+  can enable logging by saying Y to "/proc filesystem support" and
+  "Sysctl support" below and executing the command
 
      echo "scsi log token [level]" > /proc/scsi/scsi
 
+  at boot time after the /proc filesystem has been mounted.
+
   There are a number of things that can be used for 'token' (you can
   find them in the source: drivers/scsi/scsi.c), and this allows you
   to select the types of information you want, and the level allows
-  you to select the level of verbosity. If you say N here, it may be
-  harder to track down some types of SCSI problems. If you say Y here
-  your kernel will be somewhat larger, but there should be no
-  noticeable performance impact as long as you have logging turned
-  off.
+  you to select the level of verbosity. 
+
+  If you say N here, it may be harder to track down some types of SCSI
+  problems. If you say Y here your kernel will be somewhat larger, but
+  there should be no noticeable performance impact as long as you have
+  logging turned off.
 
 AdvanSys SCSI support
 CONFIG_SCSI_ADVANSYS
@@ -3389,7 +3525,7 @@ Adaptec AHA1542 support
 CONFIG_SCSI_AHA1542
   This is support for a SCSI host adapter. It is explained in section
   3.4 of the SCSI-HOWTO, available via FTP (user: anonymous) at
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  Note that Trantor was
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that Trantor was
   recently purchased by Adaptec, and some former Trantor products are
   being sold under the Adaptec name. If it doesn't work out of the
   box, you may have to change some settings in drivers/scsi/aha1542.h.
@@ -3422,10 +3558,10 @@ CONFIG_SCSI_AIC7XXX
   found by checking the help file for each of the available
   configuration options. You also want to read
   drivers/scsi/README.aic7xxx and the SCSI-HOWTO, available via FTP
-  (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note
-  that the AHA2920 SCSI host adapter is *not* supported by this
+  (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+  Note that the AHA2920 SCSI host adapter is *not* supported by this
   driver; choose "Future Domain 16xx SCSI support" instead if you have
-  one of those. 
+  one of those.
 
   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),
@@ -3452,9 +3588,9 @@ CONFIG_OVERRIDE_CMDS
 Maximum number of commands per LUN
 CONFIG_AIC7XXX_CMDS_PER_LUN
   Specify the maximum number of commands you would like to allocate
-  per LUN (a LUN is a Logical Unit Number -- some physical SCSI devices,
-  e.g. CD jukeboxes, act logically as several separate units, each of
-  which gets its own number).  
+  per LUN (a LUN is a Logical Unit Number -- some physical SCSI
+  devices, e.g. CD jukeboxes, act logically as several separate units,
+  each of which gets its own number).
 
   Reasonable figures are in the range of 14 to 32 commands per device,
   but depending on hardware could be increased or decreased from that
@@ -3476,7 +3612,9 @@ CONFIG_AIC7XXX_PROC_STATS
   small amount of overhead to each and every SCSI command the aic7xxx
   driver handles, so if you aren't really interested in this
   information, it is best to leave it disabled. This will only work if
-  you also say Y to "/proc filesystem support", below. If unsure, say N.
+  you also say Y to "/proc filesystem support", below. 
+
+  If unsure, say N.
 
 Delay in seconds after SCSI bus reset
 CONFIG_AIC7XXX_RESET_DELAY
@@ -3496,12 +3634,12 @@ CONFIG_AIC7XXX_RESET_DELAY
 BusLogic SCSI support
 CONFIG_SCSI_BUSLOGIC
   This is support for BusLogic MultiMaster and FlashPoint SCSI Host
-  Adapters.  Consult the SCSI-HOWTO, available via anonymous FTP from
+  Adapters. Consult the SCSI-HOWTO, available via anonymous FTP from
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO, and the files
   README.BusLogic and README.FlashPoint in drivers/scsi for more
-  information.  If this driver does not work correctly without
+  information. If this driver does not work correctly without
   modification, please contact the author, Leonard N. Zubkoff, by
-  email to lnz@dandelion.com.  
+  email to lnz@dandelion.com. 
 
   You can also build this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -3512,18 +3650,18 @@ CONFIG_SCSI_BUSLOGIC
 Omit BusLogic SCSI FlashPoint support
 CONFIG_SCSI_OMIT_FLASHPOINT
   This option allows you to omit the FlashPoint support from the
-  BusLogic SCSI driver.  The FlashPoint SCCB Manager code is
+  BusLogic SCSI driver. The FlashPoint SCCB Manager code is
   substantial, so users of MultiMaster Host Adapters may wish to omit
   it.
 
 DTC3180/3280 SCSI support
 CONFIG_SCSI_DTC3280
-  This is support for DTC 3180/3280 SCSI Host Adapters.  Please read
+  This is support for DTC 3180/3280 SCSI Host Adapters. Please read
   the SCSI-HOWTO, available via FTP (user: anonymous) at
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO and the file
-  drivers/scsi/README.dtc3x80.  
+  drivers/scsi/README.dtc3x80. 
 
-  This driver is also available as a module (= code which can be
+  This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called dtc.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
@@ -3532,13 +3670,13 @@ EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support
 CONFIG_SCSI_EATA_DMA
   This is support for the EATA-DMA protocol compliant SCSI Host
   Adapters like the SmartCache III/IV, SmartRAID controller families
-  and the DPT PM2011B and PM2012B controllers.  Note that there is
+  and the DPT PM2011B and PM2012B controllers. Note that there is
   also another driver for the same hardware: "EATA ISA/EISA/PCI
   support". You should only say Y to one of them. Please read the
   SCSI-HOWTO, available via FTP (user: anonymous) at
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
 
-  This driver is also available as a module (= code which can be
+  This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called eata_dma.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
@@ -3549,9 +3687,9 @@ CONFIG_SCSI_EATA_PIO
   Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
   host adapters could also use this driver but are discouraged from
   doing so, since this driver only supports hard disks and lacks
-  numerous features.  You might want to have a look at the SCSI-HOWTO,
+  numerous features. You might want to have a look at the SCSI-HOWTO,
   available via FTP (user: anonymous) at
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -3563,11 +3701,11 @@ CONFIG_SCSI_U14_34F
   This is support for the UltraStor 14F and 34F SCSI-2 host adapters.
   The source at drivers/scsi/u14-34f.c contains some information about
   this hardware. If the driver doesn't work out of the box, you may
-  have to change some settings in drivers/scsi/u14-34f.c.  Read the
+  have to change some settings in drivers/scsi/u14-34f.c. Read the
   SCSI-HOWTO, available via FTP (user: anonymous) at
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that there is also
   another driver for the same hardware: "UltraStor SCSI support",
-  below.  You should say Y to both only if you want 24F support as
+  below. You should say Y to both only if you want 24F support as
   well. 
 
   This driver is also available as a module ( = code which can be
@@ -3595,7 +3733,7 @@ CONFIG_SCSI_FUTURE_DOMAIN
   other adapters based on the Future Domain chipsets (Quantum
   ISA-200S, ISA-250MG; Adaptec AHA-2920; and at least one IBM board).
   It is explained in section 3.7 of the SCSI-HOWTO, available via FTP
-  (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  
+  (user: anonymous) at ftp://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).
@@ -3660,13 +3798,13 @@ CONFIG_SCSI_NCR53C7xx_FAST
 allow DISCONNECT
 CONFIG_SCSI_NCR53C7xx_DISCONNECT
   This enables the disconnect/reconnect feature of the NCR SCSI
-  controller.  When you say Y here, a slow SCSI device will not lock
+  controller. When you say Y here, a slow SCSI device will not lock
   the SCSI bus while processing a request, allowing simultaneous use
   of e.g. a SCSI hard disk and SCSI tape or CD-ROM drive, and
   providing much better performance when using slow and fast SCSI
   devices at the same time. Some devices, however, do not operate
   properly with this option enabled, and will cause your SCSI system
-  to hang, which might cause a system crash.  The safe answer
+  to hang, which might cause a system crash. The safe answer
   therefore is to say N.
 
 NCR53C8XX SCSI support
@@ -3676,7 +3814,7 @@ CONFIG_SCSI_NCR53C8XX
   tagged command queuing and fast synchronous data transfers up to 80
   MB/s with wide FAST-40 LVD devices and controllers.
 
-  The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895 
+  The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895
   supports FAST-40 transfers with Ultra2 LVD devices.
 
   Please read drivers/scsi/README.ncr53c8xx for more information.
@@ -3729,7 +3867,7 @@ CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
   device of yours to not support properly the target-disconnect
   feature. In that case, you would say Y here. In general however, to
   not allow targets to disconnect is not reasonable if there is more
-  than 1 device on a SCSI bus.  The normal answer therefore is N.
+  than 1 device on a SCSI bus. The normal answer therefore is N.
 
 default tagged command queue depth
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
@@ -3740,12 +3878,12 @@ CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
   this feature, enter 0 or 1 here (it doesn't matter which).
 
   The default value is 8 and should be supported by most hard disks.
-  This option has no effect for adapters with NVRAM, since the driver 
-  will get this information from the user set-up. It also can be 
+  This option has no effect for adapters with NVRAM, since the driver
+  will get this information from the user set-up. It also can be
   overridden using a boot setup option, as follows (example):
-  'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to 4, 
-  set queue depth to 16 for target 2 and target 3 on controller 0 and 
-  set queue depth to 10 for target 0 / lun 2 on controller 1.
+  'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to
+  4, set queue depth to 16 for target 2 and target 3 on controller 0
+  and set queue depth to 10 for target 0 / lun 2 on controller 1.
 
   The normal answer therefore is to go with the default 8 and to use 
   a boot command line option for devices that need to use a different 
@@ -3757,14 +3895,15 @@ maximum number of queued commands
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS
   This option allows you to specify the maximum number of commands
   that can be queued to any device, when tagged command queuing is
-  possible.  The default value is 32. Minimum is 2, maximum is 64.
-  For value less than 32, this option only saves a little memory 
-  (8*7*(32-MAXTAGS) bytes), so using less than 32 isn't worth it.
-  For value greater than 32, latency on reselection will be increased 
-  by 1 or 2 micro-seconds. So, the normal answer here is to go with the 
-  default value 32 unless you are using very large hard disks with 
-  large cache (>= 1MB) that are able to take advantage of more than 
-  32 tagged commands.
+  possible. The default value is 32. Minimum is 2, maximum is 64. For
+  value less than 32, this option only saves a little memory
+  (8*7*(32-MAXTAGS) bytes), so using less than 32 isn't worth it. For
+  value greater than 32, latency on reselection will be increased by 1
+  or 2 micro-seconds. 
+
+  So, the normal answer here is to go with the default value 32 unless
+  you are using very large hard disks with large cache (>= 1 MB) that
+  are able to take advantage of more than 32 tagged commands.
 
   There is no safe option and the default answer is recommended.
 
@@ -3798,8 +3937,8 @@ CONFIG_SCSI_NCR53C8XX_PROFILE
 IBMMCA SCSI support
 CONFIG_SCSI_IBMMCA
   This is support for the IBM SCSI adapter found in many of the PS/2
-  series computers. These machines have an MCA bus, so you need to say
-  Y to "MCA support" as well and read Documentation/mca.txt.
+  series computers. These machines have an MCA bus, so you need to
+  answer Y to "MCA support" as well and read Documentation/mca.txt.
 
   If the adapter isn't found during boot (a common problem for models
   56, 57, 76, and 77) you'll need to use the 'ibmmcascsi=<pun>' kernel
@@ -3840,14 +3979,14 @@ CONFIG_IBMMCA_SCSI_ORDER_STANDARD
   assignment of hard disks as seen from e.g. DOS or OS/2 on your
   machine, which is in addition conformant to the SCSI-standard, you
   must say Y here. This is also necessary for MCA-Linux users who want
-  to keep downward- compatibility to older releases of the
+  to keep downward compatibility to older releases of the
   IBM-MCA-SCSI-driver (older than driver-release 2.00 and older than
   June 1997).
 
   If you like to have the lowest SCSI-id assigned as drive C:, as
   modern SCSI-BIOSes do, which does not conform to the standard, but
   is widespread and common in the PC-world of today, you must say N
-  here.  If unsure, say Y.
+  here. If unsure, say Y.
 
 Reset SCSI-devices at boot time
 CONFIG_IBMMCA_SCSI_DEV_RESET
@@ -3926,8 +4065,8 @@ CONFIG_SCSI_QLOGIC_FAS
   Qlogic FastSCSI! cards as well as any other card based on the FASXX
   chip (including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards); it
   does NOT support the PCI version. The PCI versions are supported by
-  the Qlogic ISP driver though.  Information about this driver is
-  contained in drivers/scsi/README.qlogicfas.  You should also read
+  the Qlogic ISP driver though. Information about this driver is
+  contained in drivers/scsi/README.qlogicfas. You should also read
   the SCSI-HOWTO, available via FTP (user: anonymous) at
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
 
@@ -3940,12 +4079,13 @@ Qlogic ISP SCSI support (EXPERIMENTAL)
 CONFIG_SCSI_QLOGIC_ISP
   This driver works for all QLogic PCI SCSI host adapters (IQ-PCI,
   IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
-  card is supported by the "AM53/79C974 PCI SCSI" driver). If you say
-  Y here, make sure to say Y to "PCI BIOS support" as well. More
-  information is contained in the file
-  drivers/scsi/README.qlogicisp. You should also read the SCSI-HOWTO,
-  available via FTP (user: anonymous) at
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
+  card is supported by the "AM53/79C974 PCI SCSI" driver). 
+
+  If you say Y here, make sure to say Y to "PCI BIOS support" as well.
+
+  Please read the file drivers/scsi/README.qlogicisp. You should also
+  read the SCSI-HOWTO, available via FTP (user: anonymous) at
+  ftp://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).
@@ -4000,7 +4140,7 @@ CONFIG_SCSI_ULTRASTOR
 7000FASST SCSI support
 CONFIG_SCSI_7000FASST
   This driver supports the Western Digital 7000 SCSI host adapter
-  family.  Some information is in the source: drivers/scsi/wd7000.c.
+  family. Some information is in the source: drivers/scsi/wd7000.c.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you
@@ -4010,12 +4150,12 @@ CONFIG_SCSI_7000FASST
 EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support
 CONFIG_SCSI_EATA
   This driver supports all the EATA/DMA-compliant SCSI host adapters
-  and does not need any BIOS32 service.  DPT ISA and all EISA i/o
+  and does not need any BIOS32 service. DPT ISA and all EISA i/o
   addresses are probed looking for the "EATA" signature. If you said Y
   to "PCI BIOS support", the addresses of all the PCI SCSI controllers
-  reported by BIOS32 are probed as well.  You want to read
-  the start of drivers/scsi/eata.c and the SCSI-HOWTO, available via
-  FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  
+  reported by BIOS32 are probed as well. You want to read the start of
+  drivers/scsi/eata.c and the SCSI-HOWTO, available via FTP (user:
+  anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
 
   Note that there is also another driver for the same hardware
   available: "EATA-DMA support". You should say Y to only one of them.
@@ -4051,7 +4191,7 @@ CONFIG_SCSI_NCR53C406A
   This is support for the NCR53c406a SCSI host adapter. For user
   configurable parameters, check out drivers/scsi/NCR53c406.c in the
   kernel source. Also read the SCSI-HOWTO, available via FTP (user:
-  anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  
+  anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
 
   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),
@@ -4060,31 +4200,32 @@ CONFIG_SCSI_NCR53C406A
 
 Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support
 CONFIG_SCSI_DC390T
-  This driver supports  PCI SCSI host adapters  based on the Am53C974A
-  chip,  e.g.  Tekram DC390(T),  DawiControl 2974  and  some   onboard
+  This driver supports PCI SCSI host adapters based on the Am53C974A
+  chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
   PCscsi/PCnet (Am53/79C974) solutions.
+
   Documentation can be found in linux/drivers/scsi/README.tmscsim.
   
-  Note that this driver  does NOT support Tekram DC390W/U/F, which are
-  based on NCR/Symbios chips. Use the NCR53C8XX driver for those.
-  Also note, that there is another generic Am53C974 driver.
+  Note that this driver does NOT support Tekram DC390W/U/F, which are
+  based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
+  Also note that there is another generic Am53C974 driver.
 
   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.  The module  will be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
   called tmscsim.o.
 
-Skip support for other Am53/79C974 based SCSI adapters
+Omit support for other Am53/79C974 based SCSI adapters
 CONFIG_SCSI_DC390T_NOGENSUPP
-  Normally, the DC390(T) SCSI driver relies on the DC390 EEPROM to get
-  initial values  for its settings,  such as speed,  termination, etc.
-  If  it can't find  this EEPROM, it  will use  defaults  or  the user
-  supplied boot/module parameters. For details on driver configuration
-  see linux/drivers/scsi/README.tmscsim.
-
-  With this option set, if no EEPROM is found, the driver gives up and
-  thus only supports  Tekram DC390(T) adapters.  This can be useful if
-  you have a DC390(T)  and another Am53C974 based adapter,  which, for
+  If you say N here, the DC390(T) SCSI driver relies on the DC390
+  EEPROM to get initial values for its settings, such as speed,
+  termination, etc. If it can't find this EEPROM, it will use defaults
+  or the user supplied boot/module parameters. For details on driver
+  configuration see linux/drivers/scsi/README.tmscsim.
+
+  If you say Y here and if no EEPROM is found, the driver gives up and
+  thus only supports Tekram DC390(T) adapters. This can be useful if
+  you have a DC390(T) and another Am53C974 based adapter, which, for
   some reason, you want to drive with the other AM53C974 driver.
 
   If unsure, say N.
@@ -4096,8 +4237,8 @@ CONFIG_SCSI_AM53C974
   available via FTP (user: anonymous) at
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO, is for you.
 
-  Note that there is another driver for AM53C974 based adapters: The
-  Tekram DC390(T) driver.
+  Note that there is another driver for AM53C974 based adapters:
+  "Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support", above.
 
   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),
@@ -4118,7 +4259,7 @@ CONFIG_SCSI_GDTH
 IOMEGA Parallel Port ZIP drive SCSI support
 CONFIG_SCSI_PPA
   This driver supports the parallel port version of IOMEGA's ZIP drive
-  (a 100Mb removable media device). For more information about this
+  (a 100 MB removable media device). For more information about this
   driver and how to use it you should read the file
   drivers/scsi/README.ppa. You should also read the SCSI-HOWTO, which
   is available via FTP (user: anonymous) from
@@ -4141,17 +4282,13 @@ CONFIG_SCSI_PPA_HAVE_PEDANTIC
   EPP (Enhanced Parallel Port) is a standard for parallel ports which
   allows them to act as expansion buses that can handle up to 64
   peripheral devices. Some parallel port chipsets are slower than
-  their motherboard, and so we have to control the state of the FIFO
-  every now and then to avoid data loss.  The permitted values for
-  this option are 0 (don't check FIFO), 1 (check FIFO every 4 bytes),
-  2 (check FIFO every other byte) and 3 (check FIFO every time). If
-  your EPP chipset is from the SMC series, you are likely to have to
-  set this value greater than 0.
-
-SGI wd93 Scsi Driver
-CONFIG_SCSI_SGIWD93
-  This is the SCSI driver for WD33C93 / WD33C95 SCSI chips used in many
-  SGI machines.
+  their motherboard, and so we have to control the state of the
+  chipset's FIFO queue every now and then to avoid data loss. This
+  will be done if you say Y here. 
+  
+  If your EPP chipset is from the SMC series, you are likely to have
+  to say Y here. Generally, saying Y is the safe option and slows
+  things down a bit.
 
 SCSI Debug host simulator.
 CONFIG_SCSI_DEBUG
@@ -4175,18 +4312,18 @@ CONFIG_FC4
 
 Sun SOC
 CONFIG_FC4_SOC
-  Serial Optical Channel is an interface card with one or two Fibre Optic
-  ports, each of which can be connected to a disk array. Only the SBus
-  incarnation of the adapter is supported at the moment.
+  Serial Optical Channel is an interface card with one or two Fibre
+  Optic ports, each of which can be connected to a disk array. Only
+  the SBus incarnation of the adapter is supported at the moment.
 
 SparcSTORAGE Array 100 and 200 series
 CONFIG_SCSI_PLUTO
-  If you never bought a disk array made by Sun, go with N.  
+  If you never bought a disk array made by Sun, go with N. 
 
 AcornSCSI support
 CONFIG_SCSI_ACORNSCSI_3
-  This enables support for the Acorn SCSI card (aka30).  If you have an
-  Acorn system with one of these, say Y.  If unsure, say N.
+  This enables support for the Acorn SCSI card (aka30). If you have an
+  Acorn system with one of these, say Y. If unsure, say N.
 
 Acorn SCSI tagged queue support
 CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
@@ -4199,42 +4336,42 @@ CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
 
 Acorn SCSI Synchronous transfers support
 CONFIG_SCSI_ACORNSCSI_SYNC
-  Say Y here to enable synchronous transfer negotiation with all targets
-  on the Acorn SCSI card.
+  Say Y here to enable synchronous transfer negotiation with all
+  targets on the Acorn SCSI card.
 
   In general, this improves performance; however some SCSI devices
   don't implement it properly, so the safe answer is N.
 
 Oak SCSI support
 CONFIG_SCSI_OAK1
-  This enables support for the Oak SCSI card.  If you have an Acorn system
-  with one of these, say Y.  If unsure, say N.
+  This enables support for the Oak SCSI card. If you have an Acorn
+  system with one of these, say Y. If unsure, say N.
 
 Cumana SCSI I support
 CONFIG_SCSI_CUMANA_1
-  This enables support for the Cumana SCSI I card.  If you have an Acorn
-  system with one of these, say Y.  If unsure, say N.
+  This enables support for the Cumana SCSI I card. If you have an
+  Acorn system with one of these, say Y. If unsure, say N.
 
 Cumana SCSI II support
 CONFIG_SCSI_CUMANA_2
-  This enables support for the Cumana SCSI II card.  If you have an Acorn
-  system with one of these, say Y.  If unsure, say N.
+  This enables support for the Cumana SCSI II card. If you have an
+  Acorn system with one of these, say Y. If unsure, say N.
 
 EcoSCSI support
 CONFIG_SCSI_ECOSCSI
-  This enables support for the EcoSCSI card -- a small card that sits in
-  the Econet socket.  If you have an Acorn system with one of these,
-  say Y.  If unsure, say N.
+  This enables support for the EcoSCSI card -- a small card that sits
+  in the Econet socket. If you have an Acorn system with one of these,
+  say Y. If unsure, say N.
 
 EESOX SCSI support
 CONFIG_SCSI_EESOXSCSI
-  This enables support for the EESOX SCSI card.  If you have an Acorn
+  This enables support for the EESOX SCSI card. If you have an Acorn
   system with one of these, say Y, otherwise say N.
 
 Powertec SCSI support
 CONFIG_SCSI_POWERTECSCSI
-  This enables support for the Powertec SCSI card on Acorn systems.  If
-  you have one of these, say Y.  If unsure, say N.  
+  This enables support for the Powertec SCSI card on Acorn systems. If
+  you have one of these, say Y. If unsure, say N.
 
 Network device support?
 CONFIG_NETDEVICES
@@ -4255,8 +4392,8 @@ CONFIG_NETDEVICES
   you want to use under Linux (make sure you know its name because you
   will be asked for it and read the Ethernet-HOWTO (especially if you
   plan to use more than one network card under Linux), available from
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini) or if you want to use
-  SLIP (Serial Line Internet Protocol is the protocol used to send
+  ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini) or if you want to
+  use SLIP (Serial Line Internet Protocol is the protocol used to send
   Internet traffic over telephone lines or null modem cables) or CSLIP
   (compressed SLIP) or PPP (Point to Point Protocol, a better and
   newer replacement for SLIP) or PLIP (Parallel Line Internet Protocol
@@ -4266,7 +4403,7 @@ CONFIG_NETDEVICES
 
   Make sure to read the NET-2-HOWTO. Eventually, you will have to read
   Olaf Kirch's excellent and free book "Network Administrator's
-  Guide", to be found in sunsite.unc.edu:/pub/Linux/docs/LDP. If
+  Guide", to be found in ftp://sunsite.unc.edu:/pub/Linux/docs/LDP. If
   unsure, say Y.
 
 Dummy net driver support
@@ -4293,10 +4430,11 @@ CONFIG_SLIP
   Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
   connect to your Internet service provider or to connect to some
   other local Unix box or if you want to configure your Linux box as a
-  Slip/CSlip server for other people to dial in.  SLIP (Serial Line
-  Internet Protocol) is a protocol used to send Internet traffic
-  over telephone lines or serial cables (also known as
-  null modems); nowadays, the PPP is a more common protocol than SLIP. 
+  Slip/CSlip server for other people to dial in. SLIP (Serial Line
+  Internet Protocol) is a protocol used to send Internet traffic over
+  serial connections such as telephone lines or null modem cables;
+  nowadays, the protocol PPP is more commonly used for this same
+  purpose.
 
   Normally, your access provider has to support SLIP in order for you
   to be able to use it, but there is now a SLIP emulator called SLiRP
@@ -4313,7 +4451,7 @@ CONFIG_SLIP
   http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html (to browse
   the WWW, you need to have access to a machine on the Internet that
   has a program like lynx or netscape)). SLIP support will enlarge
-  your kernel by about 4kB. If unsure, say N.
+  your kernel by about 4 KB. 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),
@@ -4325,9 +4463,9 @@ CSLIP compressed headers
 CONFIG_SLIP_COMPRESSED
   This protocol is faster than SLIP because it uses compression on the
   TCP/IP headers (not on the data itself), but it has to be supported
-  on both ends. Ask your access provider if you are not sure and say
-  Y, just in case. You will still be able to use plain SLIP. If you
-  plan to use SLiRP, the SLIP emulator (available via FTP (user:
+  on both ends. Ask your access provider if you are not sure and
+  answer Y, just in case. You will still be able to use plain SLIP. If
+  you plan to use SLiRP, the SLIP emulator (available via FTP (user:
   anonymous) from
   ftp://sunsite.unc.edu/pub/Linux/system/network/serial/) which allows
   you to use SLIP over a regular dial up shell connection, you
@@ -4371,9 +4509,9 @@ CONFIG_PPP
 
   To use PPP, you need an additional program called pppd as described
   in Documentation/networking/ppp.txt and in the PPP-HOWTO, available
-  from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you upgrade from an
-  older kernel, you might need to upgrade pppd as well. The PPP option
-  enlarges your kernel by about 16kB.
+  from ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you upgrade
+  from an older kernel, you might need to upgrade pppd as well. The
+  PPP option enlarges your kernel by about 16 KB.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -4404,13 +4542,13 @@ CONFIG_NET_RADIO
 STRIP (Metricom Starmode radio IP)
 CONFIG_STRIP
   Say Y if you have a Metricom radio and intend to use Starmode Radio
-  IP.  STRIP is a radio protocol developed for the MosquitoNet project
+  IP. STRIP is a radio protocol developed for the MosquitoNet project
   (On the WWW at http://mosquitonet.stanford.edu/; to browse the WWW,
   you need to have access to a machine on the Internet that has a
   program like lynx or netscape) to send Internet traffic using
-  Metricom radios.  Metricom radios are small, battery powered,
+  Metricom radios. Metricom radios are small, battery powered,
   100kbit/sec packet radio transceivers, about the size and weight of
-  a cellular telephone.  (You may also have heard them called
+  a cellular telephone. (You may also have heard them called
   "Metricom modems" but we avoid the term "modem" because it misleads
   many people into thinking that you can plug a Metricom modem into a
   phone line and use it as a modem.)  
@@ -4458,7 +4596,7 @@ CONFIG_LAPBETHER
   which allows you to open an LAPB point-to-point connection to some
   other computer on your Ethernet network. In order to do this, you
   need to say Y or M to the driver for your Ethernet card as well as
-  to "LAPB Data Link Driver".  
+  to "LAPB Data Link Driver". 
 
   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),
@@ -4495,8 +4633,8 @@ Shortwave radio modem driver support for WSS and Crystal cards
 CONFIG_HFMODEM_WSS
   This option enables the hfmodem driver to use WindowsSoundSystem
   compatible cards. These cards feature a codec chip from either
-  Analog Devices (such as AD1848, AD1845) or Crystal
-  Semiconductors (such as CS4248, CS423x).
+  Analog Devices (such as AD1848, AD1845) or Crystal Semiconductors
+  (such as CS4248, CS423x).
 
 PLIP (parallel port) support
 CONFIG_PLIP
@@ -4504,9 +4642,9 @@ CONFIG_PLIP
   reasonably fast mini network consisting of two (or, rarely, more)
   local machines. A PLIP link from a Linux box is a popular means to
   install a Linux distribution on a machine which doesn't have a CDROM
-  drive (a minimal system has to be transferred with floppies
-  first). The kernels on both machines need to have this PLIP option
-  enabled for this to work.
+  drive (a minimal system has to be transferred with floppies first).
+  The kernels on both machines need to have this PLIP option enabled
+  for this to work.
 
   The PLIP driver has two modes, mode 0 and mode 1. The parallel ports
   (the connectors at the computers with 25 holes) are connected with
@@ -4527,9 +4665,9 @@ CONFIG_PLIP
   NET-2-HOWTO in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that
   the PLIP protocol was changed and this PLIP driver won't work
   together with the PLIP support in Linux versions 1.0.x. This option
-  enlarges your kernel by about 8kB.
+  enlarges your kernel by about 8 KB.
 
-  If you want to compile this as a module (= code which can be
+  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 as well as
   Documentation/networking/net-modules.txt. The module will be called
@@ -4539,8 +4677,8 @@ EQL (serial line load balancing) support
 CONFIG_EQUALIZER
   If you have two serial connections to some other computer (this
   usually requires two modems and two telephone lines) and you use
-  SLIP (the protocol for sending Internet traffic over telephone
-  lines) or PPP (a better SLIP) on them, you can make them behave
+  SLIP (the protocol for sending Internet traffic over telephone
+  lines) or PPP (a better SLIP) on them, you can make them behave
   like one double speed connection using this driver. Naturally, this
   has to be supported at the other end as well, either with a similar
   EQL Linux driver or with a Livingston Portmaster 2e. Say Y if you
@@ -4565,8 +4703,8 @@ CONFIG_ETHERTAP
   to the device tap0; everything the kernel wants to send out over the
   device tap0 can instead be read by the user from /dev/tap0: the user
   mode program replaces the LAN that would be attached to an ordinary
-  Ethernet device.  Please read the file
-  Documentation/networking/ethertap.txt for more information.  
+  Ethernet device. Please read the file
+  Documentation/networking/ethertap.txt for more information. 
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -4639,7 +4777,7 @@ CONFIG_ECONET
 
 AUN over UDP
 CONFIG_ECONET_AUNUDP
-  Say Y here if you want to send Econet/AUN traffic over a UDP
+  Say Y here if you want to send Econet/AUN traffic over a UDP
   connection (UDP is a packet based protocol that runs on top of the
   Internet protocol IP) using an ordinary Ethernet network card.
 
@@ -4669,7 +4807,7 @@ CONFIG_WAN_ROUTER
 
   WAN routing support is always built as a module ( = code which can
   be inserted in and removed from the running kernel whenever you
-  want).  The module is called wanrouter.o.  For general information
+  want). The module is called wanrouter.o. For general information
   about modules read Documentation/modules.txt.
 
 Fast switching (read help!)
@@ -4695,7 +4833,7 @@ CONFIG_NET_HW_FLOWCONTROL
   8390 can be found at
   ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz). Really, this
   option is applicable to any machine attached to a fast enough
-  network, and even a 10Mb NIC is able to kill a not very slow box,
+  network, and even a 10 Mb NIC is able to kill a not very slow box,
   such as a 120MHz Pentium.
 
   However, do not say Y here if you did not experience any serious
@@ -4712,20 +4850,20 @@ CONFIG_NET_SCHED
   When the kernel has several packets to send out over the network
   devices, it has to make a decision which one to send first. This is
   especially important if some of the network devices are real time
-  devices that need a certain minimum data flow rate.  There are
+  devices that need a certain minimum data flow rate. There are
   several different algorithms for how to do this "fairly"; they are
-  called packet schedulers. You can attach different schedulers to
-  different network devices. If you want to stick to the default
+  called packet schedulers. If you want to stick to the default
   scheduling algorithm, say N here. If you want to experiment with a
-  couple of different algorithms, say Y. Currently, this is only
+  couple of different algorithms, say Y. You can then attach different
+  schedulers to different network devices. Currently, this is only
   recommended for experts.
 
   To administer these schedulers, you'll need the user-level utilities
   from the package iproute2+tc at ftp://ftp.inr.ac.ru/ip-routing/
 
   If you say Y here and to "/proc filesystem" below, you will be able
-  to read status information about priority schedulers from
-  the file /proc/net/psched.
+  to read status information about priority schedulers from the file
+  /proc/net/psched.
   
   The available schedulers are listed in the following questions; you
   can say Y to as many as you like. If unsure, say N now.
@@ -4873,24 +5011,25 @@ CONFIG_NET_PROFILE
   performance will be written to /proc/net/profile. If you don't know
   what it is about, you don't need it: say N.
 
-#Comtrol Hostess SV-11 support
-#CONFIG_HOSTESS_SV11
-###
-### I don't know what this is.
-###  
+Comtrol Hostess SV-11 support
+CONFIG_HOSTESS_SV11
+  This is a network card for high speed synchronous serial links. It
+  is commonly used to connect to Cisco equipment over HSSI links. At
+  this point, the driver can only be compiled as a module.
 
 WAN Drivers
 CONFIG_WAN_DRIVERS
   Say Y to this option if your Linux box contains a WAN card and you
-  are planning to use the box as a WAN ( = Wide Area Network) router
+  are planning to use the box as a WAN ( = Wide Area Network) router 
   ( = device used to interconnect local area networks over wide area
-  communication links, such as leased lines and public data networks,
-  e.g. X.25 and frame relay) and you will be offered a list of drivers
+  communication links, such as leased lines or public data networks,
+  e.g. X.25 or frame relay) and you will be offered a list of drivers
   for WAN cards currently available. For more information, read
-  Documentation/networking/wan-router.txt. Note that the answer to
-  this question won't directly affect the kernel: saying N will just
-  cause this configure script to skip all the questions about WAN
-  card drivers. If unsure, say N.
+  Documentation/networking/wan-router.txt.
+
+  Note that the answer to this question won't directly affect the
+  kernel: saying N will just cause this configure script to skip all
+  the questions about WAN card drivers. If unsure, say N.
 
 Sangoma WANPIPE(tm) multiprotocol cards
 CONFIG_VENDOR_SANGOMA
@@ -4898,12 +5037,12 @@ CONFIG_VENDOR_SANGOMA
   browse the WWW, you need to have access to a machine on the Internet
   that has a program like lynx or netscape) is a family of intelligent
   multiprotocol WAN adapters with data transfer rates up to T1 (1.544
-  Mbps).  They are also known as Synchronous Data Link Adapters (SDLA)
+  Mbps). They are also known as Synchronous Data Link Adapters (SDLA)
   and designated S502E(A), S503 or S508. These cards support the X.25,
   Frame Relay, and PPP protocols. If you have one or more of these
-  cards, say Y to this option and read
-  Documentation/networking/wanpipe.txt.  The next questions will ask
-  you about the protocols you want the driver to support. 
+  cards, say Y to this option; you may then also want to read the file
+  Documentation/networking/wanpipe.txt. The next questions will ask
+  you about the protocols you want the driver to support.
 
   The driver will be compiled as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -4912,8 +5051,8 @@ CONFIG_VENDOR_SANGOMA
 
 Maximum number of cards
 CONFIG_WANPIPE_CARDS
-  Enter number of WANPIPE adapters installed in your machine.  The
-  driver can support up to 8 cards.  You may enter more than you
+  Enter number of WANPIPE adapters installed in your machine. The
+  driver can support up to 8 cards. You may enter more than you
   actually have if you plan to add more cards in the future without
   re-compiling the driver, but remember that in this case you'll waste
   some kernel memory (about 1K per card).
@@ -4923,15 +5062,15 @@ CONFIG_WANPIPE_X25
   Say Y to this option if you are planning to connect a WANPIPE card
   to an X.25 network. You should then also have said Y to "CCITT X.25
   Packet Layer" and "LAPB Data Link Driver", above. If you say N, the
-  X.25 support will not be included in the driver (saves about 16K of
-  kernel memory).
+  X.25 support will not be included in the driver (saves about 16 KB
+  of kernel memory).
 
 WANPIPE Frame Relay support
 CONFIG_WANPIPE_FR
   Say Y to this option if you are planning to connect a WANPIPE card
   to a frame relay network. You should then also have said Y to "Frame
   Relay (DLCI) support", above. If you say N, the frame relay
-  support will not be included in the driver (saves about 16K of
+  support will not be included in the driver (saves about 16 KB of
   kernel memory).
 
 WANPIPE PPP support
@@ -4940,7 +5079,7 @@ CONFIG_WANPIPE_PPP
   to a leased line using Point-to-Point protocol (PPP). You should
   then also have said Y to "PPP (point-to-point) support", above. If
   you say N, the PPP support will not be included in the driver (saves
-  about 16K of kernel memory).
+  about 16 KB of kernel memory).
 
 Ethernet (10 or 100Mbit)
 CONFIG_NET_ETHERNET
@@ -4980,8 +5119,8 @@ CONFIG_SUN_LANCE
 
 Sun Intel Ethernet support
 CONFIG_SUN_INTEL
-  This is support for the Intel Ethernet cards on some Sun workstations
-  (all those with a network interface 'ie0' under SunOS).
+  This is support for the Intel Ethernet cards on some Sun
+  workstations (all those with a network interface 'ie0' under SunOS).
 
 Western Digital/SMC cards
 CONFIG_NET_VENDOR_SMC
@@ -5042,7 +5181,7 @@ SMC Ultra32 EISA support
 CONFIG_ULTRA32
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available via FTP (user: anonymous) in
-  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.  
+  ftp://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).
@@ -5069,8 +5208,9 @@ CONFIG_SMC9194
 PCI NE2000 support
 CONFIG_NE2K_PCI
   This driver is for NE2000 compatible PCI cards. It will not work
-  with ISA NE2000 cards. If you have a PCI NE2000 network (Ethernet)
-  card, say Y and read the Ethernet-HOWTO, available via FTP (user:
+  with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
+  support" below). If you have a PCI NE2000 network (Ethernet) card,
+  say Y and read the Ethernet-HOWTO, available via FTP (user:
   anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
 
   This driver is also available as a module ( = code which can be
@@ -5257,8 +5397,8 @@ CONFIG_EL3
 CONFIG_VORTEX
   If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597)
   or "Boomerang" series (EtherLink XL 3c900 or 3c905) network
-  (Ethernet) card, say Y and read the Ethernet-HOWTO, available via FTP
-  (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+  (Ethernet) card, say Y and read the Ethernet-HOWTO, available via
+  FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
   More specific information is in Documentation/networking/vortex.txt
   and in the comments at the beginning of drivers/net/3c59x.c.
 
@@ -5287,9 +5427,9 @@ CONFIG_ARCNET
   (arguably) beautiful poetry in Documentation/networking/arcnet.txt.
 
   You need both this driver, and the driver for the particular ARCnet
-  chipset of your card. If you don't know, then it's probably a 
-  COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset support"
-  below.
+  chipset of your card. If you don't know, then it's probably a
+  COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset
+  support" below.
 
   You might also want to have a look at the Ethernet-HOWTO, available
   via FTP (user: anonymous) in
@@ -5305,25 +5445,25 @@ CONFIG_ARCNET
 Enable arc0e (ARCnet "ether-encap" packet format)
 CONFIG_ARCNET_ETH
   This allows you to use "Ethernet encapsulation" with your ARCnet
-  card via the virtual arc0e device.  You only need arc0e if you want
+  card via the virtual arc0e device. You only need arc0e if you want
   to talk to nonstandard ARCnet software, specifically,
-  DOS/Windows-style "NDIS" drivers.  You do not need to say Y here to
+  DOS/Windows-style "NDIS" drivers. You do not need to say Y here to
   communicate with industry-standard RFC1201 implementations, like the
-  arcether.com packet driver or most DOS/Windows ODI drivers.  RFC1201
-  is included automatically as the arc0 device.  Please read the
+  arcether.com packet driver or most DOS/Windows ODI drivers. RFC1201
+  is included automatically as the arc0 device. Please read the
   ARCnet documentation in Documentation/networking/arcnet.txt for more
   information about using arc0e and arc0s.
 
 Enable arc0s (ARCnet RFC1051 packet format)
 CONFIG_ARCNET_1051
   This allows you to use RFC1051 with your ARCnet card via the virtual
-  arc0s device.  You only need arc0s if you want to talk to ARCnet
+  arc0s device. You only need arc0s if you want to talk to ARCnet
   software complying with the "old" standard, specifically, the DOS
   arcnet.com packet driver, Amigas running AmiTCP, and some variants
-  of NetBSD.  You do not need to say Y here to communicate with
+  of NetBSD. You do not need to say Y here to communicate with
   industry-standard RFC1201 implementations, like the arcether.com
-  packet driver or most DOS/Windows ODI drivers.  RFC1201 is included
-  automatically as the arc0 device.  Please read the ARCnet
+  packet driver or most DOS/Windows ODI drivers. RFC1201 is included
+  automatically as the arc0 device. Please read the ARCnet
   documentation in Documentation/networking/arcnet.txt for more
   information about using arc0e and arc0s.
 
@@ -5343,7 +5483,7 @@ ARCnet COM90xx (IO mapped) chipset driver
 CONFIG_ARCNET_COM90xxIO
   This is the chipset driver for the COM90xx cards, using them in
   IO-mapped mode instead of memory-mapped mode. This is slower than
-  the normal driver.  Only use it if your card doesn't support shared
+  the normal driver. Only use it if your card doesn't support shared
   memory. 
 
   This driver is also available as a module ( = code which can be
@@ -5533,7 +5673,13 @@ CONFIG_NE2000
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available via FTP (user: anonymous) in
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Many Ethernet cards
-  without a specific driver are compatible with NE2000.
+  without a specific driver are compatible with NE2000. 
+
+  If you have a PCI NE2000 card however, say N here and Y to "PCI
+  NE2000 support", above. If you have a NE2000 card and are running on
+  an MCA system (a bus system used on some IBM PS/2 computers and
+  laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
+  below.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -5547,6 +5693,18 @@ CONFIG_SK_G16
   the Ethernet-HOWTO, available via FTP (user: anonymous) in
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
 
+NE/2 (ne2000 MCA version) support
+CONFIG_NE2_MCA
+  If you have a network (Ethernet) card of this type, say Y and read
+  the Ethernet-HOWTO, available via FTP (user: anonymous) in
+  ftp://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).
+  The module will be called ne2.o. 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.
+
 EISA, VLB, PCI and on board controllers
 CONFIG_NET_EISA
   This is another class of network cards which attach directly to the
@@ -5562,8 +5720,8 @@ CONFIG_NET_EISA
 
 AMD PCnet32 (VLB and PCI) support
 CONFIG_PCNET32
-  If you have a PCnet32 or PCnetPCI based network (Ethernet) card, say
-  Y here and read the Ethernet-HOWTO, available via FTP (user:
+  If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
+  answer Y here and read the Ethernet-HOWTO, available via FTP (user:
   anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
 
   This driver is also available as a module ( = code which can be
@@ -5584,18 +5742,6 @@ CONFIG_AC3200
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-Racal-Interlan EISA ES3210 support
-CONFIG_ES3210
-  If you have a network (Ethernet) card of this type, say Y and read
-  the Ethernet-HOWTO, available via FTP (user: anonymous) in
-  ftp://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).
-  The module will be called es3210.o. 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.
-
 Mylex EISA LNE390A/LNE390B support
 CONFIG_LNE390
   If you have a network (Ethernet) card of this type, say Y and read
@@ -5725,6 +5871,29 @@ CONFIG_TLAN
 
   Please email feedback to james.banks@caldera.com.
 
+VIA Rhine support
+CONFIG_VIA_RHINE
+  If you have a VIA "rhine" based network card (Rhine-I (3043) or
+  Rhine-2 (VT86c100A)), say Y here.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called via-rhine.o. 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.
+
+Racal-Interlan EISA ES3210 support
+CONFIG_ES3210
+  If you have a network (Ethernet) card of this type, say Y and read
+  the Ethernet-HOWTO, available via FTP (user: anonymous) in
+  ftp://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).
+  The module will be called es3210.o. 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.
+
 SMC EtherPower II (EXPERIMENTAL)
 CONFIG_EPIC100
   If you have an SMC EtherPower II 9432 PCI Ethernet network card
@@ -5738,11 +5907,10 @@ CONFIG_EPIC100
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-VIA Rhine support
-CONFIG_VIA_RHINE
-  If you have a VIA "rhine" based network card (Rhine-I (3043) or
-  Rhine-2 (VT86c100A)), say Y here. To build this driver as a module
-  say M.
+SGI Seeq ethernet controller support
+CONFIG_SGISEEQ
+  Say Y here if you have an Seeq based Ethernet network card. This is
+  used in many Silicon Graphics machines.
 
 Zenith Z-Note support
 CONFIG_ZNET
@@ -5859,9 +6027,9 @@ CONFIG_SHAPER
   The traffic shaper is a virtual network device that allows you to
   limit the rate of outgoing data flow over some other network
   device. See Documentation/networking/shaper.txt for more
-  information.  To set up and configure shaper devices, you need the
+  information. To set up and configure shaper devices, you need the
   shapecfg program, available via FTP (user: anonymous) from
-  ftp://shadow.cabi.net/pub/Linux in the shaper package.  
+  ftp://shadow.cabi.net/pub/Linux in the shaper package. 
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -5883,9 +6051,44 @@ CONFIG_DEFXX
   This is support for the DIGITAL series of EISA (DEFEA) and PCI
   (DEFPA) controllers which can connect you to a local FDDI network.
 
-SGI Seeq ethernet controller support
-  This is a driver for the Seeq based Ethernet adapters used in many
-  Silicon Graphics machines.
+HIgh Performance Parallel Interface support (EXPERIMENTAL)
+CONFIG_HIPPI
+  HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
+  1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
+  can run over copper (25m) or fiber (300m on multi-mode or 10km on
+  single-mode). HIPPI networks are commonly used for clusters and to
+  connect to super computers. If you are connected to a HIPPI network
+  and have a HIPPI network card in your computer that you want to use
+  under Linux, say Y here (you must also remember to enable the driver
+  for your HIPPI card below). Most people will say N here.
+  
+CERN HIPPI PCI adapter support
+CONFIG_CERN_HIPPI
+  Say Y here if this is your PCI HIPPI network card.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called cern_hippi.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt. If unsure,
+  say N.
+
+Essential RoadRunner HIPPI PCI adapter support
+CONFIG_ROADRUNNER
+  Say Y here if this is your PCI HIPPI network card.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called rrunner.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt. If unsure,
+  say N.
+
+Use large TX/RX rings
+CONFIG_ROADRUNNER_LARGE_RINGS
+  If you say Y here, the RoadRunner driver will preallocate up to 2 MB
+  of additional memory to allow for fastest operation, both for
+  transmitting and receiving. This memory cannot be used by any other
+  kernel code or by user space programs. Say Y here only if you have
+  the memory.
 
 Acorn Ether1 card
 CONFIG_ARM_ETHER1
@@ -5925,20 +6128,20 @@ CONFIG_CD_NO_IDESCSI
   file drivers/cdrom/<driver_name>.h where you can define your
   interface parameters and switch some internal goodies. 
 
-  All these CDROM drivers are also usable as a module (= code which
+  All these CDROM drivers are also usable as a module ( = code which
   can be inserted in and removed from the running kernel whenever you
   want). If you want to compile them as module, say M instead of Y and
   read Documentation/modules.txt. 
 
-  If you want to use any of these CDROM drivers, you also have to say
-  Y or M to "ISO 9660 CDROM filesystem support" below (this answer will
-  get "defaulted" for you if you enable any of the Linux CDROM
-  drivers).
+  If you want to use any of these CDROM drivers, you also have to
+  answer Y or M to "ISO 9660 CDROM filesystem support" below (this
+  answer will get "defaulted" for you if you enable any of the Linux
+  CDROM drivers).
 
 Sony CDU31A/CDU33A CDROM support
 CONFIG_CDU31A
   These CDROM drives have a spring-pop-out caddyless drawer, and a
-  rectangular green LED centered beneath it.  NOTE: these CDROM drives
+  rectangular green LED centered beneath it. NOTE: these CDROM drives
   will not be auto detected by the kernel at boot time; you have to
   provide the interface address as an option to the kernel at boot
   time as described in Documentation/cdrom/cdu31a or fill in your
@@ -5964,13 +6167,13 @@ CONFIG_MCD
   IDE/ATAPI models). Please also the file Documentation/cdrom/mcd.
 
   With the old LU-005 model, the whole drive chassis slides out for cd
-  insertion.  The FX-xxx models use a motorized tray type mechanism.
+  insertion. The FX-xxx models use a motorized tray type mechanism.
   Note that this driver does not support XA or MultiSession CDs
-  (PhotoCDs).  There is a new driver (next question) which can do
+  (PhotoCDs). There is a new driver (next question) which can do
   this. If you want that one, say N here.
 
   If the driver doesn't work out of the box, you might want to have a
-  look at drivers/cdrom/mcd.h.  
+  look at drivers/cdrom/mcd.h. 
 
   If you say Y here, you should also say Y or M to "ISO 9660 CDROM
   filesystem support" below, because that's the filesystem used on
@@ -5985,10 +6188,11 @@ Mitsumi [XA/MultiSession] support
 CONFIG_MCDX
   Use this driver if you want to be able to read XA or MultiSession
   CDs (PhotoCDs) as well as ordinary CDs with your Mitsumi LU-005,
-  FX-001 or FX-001D CDROM drive. In addition, this driver uses much less
-  kernel memory than the old one, if that is a concern. This driver is
-  able to support more than one drive, but each drive needs a separate
-  interface card. Please read the file Documentation/cdrom/mcdx. 
+  FX-001 or FX-001D CDROM drive. In addition, this driver uses much
+  less kernel memory than the old one, if that is a concern. This
+  driver is able to support more than one drive, but each drive needs
+  a separate interface card. Please read the file
+  Documentation/cdrom/mcdx.
 
   If you say Y here, you should also say Y or M to "ISO 9660 CDROM
   filesystem support" below, because that's the filesystem used on
@@ -6049,7 +6253,7 @@ Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support
 CONFIG_AZTCD
   This is your driver if you have an Aztech CDA268-01A, Orchid
   CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCDROM CR520 or
-  CR540 CDROM drive.  This driver -- just like all these CDROM drivers
+  CR540 CDROM drive. This driver -- just like all these CDROM drivers
   -- is NOT for CDROM drives with IDE/ATAPI interfaces, such as Aztech
   CDA269-031SE. Please read the file Documentation/cdrom/aztcd. 
 
@@ -6078,7 +6282,7 @@ CONFIG_CDU535
 
 Goldstar R420 CDROM support
 CONFIG_GSCD
-  If this is your CDROM drive, say Y here.  As described in
+  If this is your CDROM drive, say Y here. As described in the file
   linux/Documentation/cdrom/gscd, you might have to change a setting
   in the file linux/drivers/cdrom/gscd.h before compiling the
   kernel. Please read the file Documentation/cdrom/gscd. 
@@ -6095,7 +6299,7 @@ CONFIG_GSCD
 Philips/LMS CM206 CDROM support
 CONFIG_CM206
   If you have a Philips/LMS CDROM drive cm206 in combination with a
-  cm260 host adapter card, say Y here.  Please also read the file
+  cm260 host adapter card, say Y here. Please also read the file
   Documentation/cdrom/cm206. 
 
   If you say Y here, you should also say Y or M to "ISO 9660 CDROM
@@ -6139,9 +6343,9 @@ CONFIG_SJCD
 Soft configurable cdrom interface card support
 CONFIG_CDI_INIT
   If you want to include boot-time initialization of any cdrom
-  interface card that is software configurable, say Y here.  Currently
+  interface card that is software configurable, say Y here. Currently
   only the ISP16/MAD16/Mozart sound cards with built-in cdrom
-  interfaces are supported.  
+  interfaces are supported. 
 
   Note that the answer to this question doesn't directly affect the
   kernel: saying N will just cause this configure script to skip all
@@ -6149,11 +6353,11 @@ CONFIG_CDI_INIT
 
 ISP16/MAD16/Mozart soft configurable cdrom interface support
 CONFIG_ISP16_CDI
-  These are sound cards with with built-in cdrom interfaces using the
-  OPTi 82C928 or 82C929 chips. Say Y here to have them detected and
+  These are sound cards with built-in cdrom interfaces using the OPTi
+  82C928 or 82C929 chips. Say Y here to have them detected and
   possibly configured at boot time. In addition, You'll have to say Y
   to a driver for the particular cdrom drive you have attached to the
-  card. Read Documentation/cdrom/isp16 for details.  
+  card. Read Documentation/cdrom/isp16 for details.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -6172,15 +6376,15 @@ CONFIG_QUOTA
 
 Minix fs support
 CONFIG_MINIX_FS
-  Minix is a simple operating system used in many classes about
-  OS's. The minix filesystem (= method to organize files on a hard disk
+  Minix is a simple operating system used in many classes about OS's.
+  The minix filesystem (method to organize files on a hard disk
   partition or a floppy disk) was the original filesystem for Linux,
-  has been superseded by the second extended filesystem ext2fs but is
-  still used for root/boot and other floppies or ram disks since it is
-  leaner. You don't want to use it on your hard disk because of certain
-  built-in restrictions. This option will enlarge your kernel by about
-  25 kB. Everyone should say Y or M so that they are able to read this
-  common floppy format.  
+  has since been superseded by the second extended filesystem ext2fs
+  but is still being used for root/boot and other floppies or ram
+  disks since it is leaner. You don't want to use it on your hard disk
+  because of certain built-in restrictions. This option will enlarge
+  your kernel by about 25 kB. Everyone should say Y or M so that they
+  are able to read this common floppy filesystem.
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -6190,7 +6394,7 @@ CONFIG_MINIX_FS
 
 Second extended fs support
 CONFIG_EXT2_FS
-  This is the de facto standard Linux filesystem (method to organize
+  This is the de facto standard Linux filesystem (method to organize
   files on a storage device) for hard disks. 
 
   You want to say Y here, unless you intend to use Linux exclusively
@@ -6218,10 +6422,13 @@ CONFIG_EXT2_FS
   directories on ext2 filesystems, use chattr ("man chattr").
   
   Ext2fs partitions can be read from within DOS using the ext2tool
-  package (available via FTP (user: anonymous) from
+  command line tool package (available via FTP (user: anonymous) from
   ftp://sunsite.unc.edu/pub/Linux/system/filesystems/ext2) and from
-  within Windows 95 and Windows NT using the ex2fs explorer available
-  from http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm.
+  within Windows NT using the ext2nt command line tool package from
+  ftp://sunsite.unc.edu/pub/Linux/utils/dos. Explore2fs is a graphical
+  explorer for ext2fs partitions which runs on Windows 95 and Windows
+  NT and includes experimental write support; it is available from
+  http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm.
 
   If you want to compile this filesystem as a module ( = code which
   can be inserted in and removed from the running kernel whenever you
@@ -6294,33 +6501,33 @@ CONFIG_MSDOS_FS
 
   Another way to read and write MSDOS floppies from within Linux (but
   not transparently) is with the mtools ("man mtools") program suite,
-  which doesn't require the msdos filesystem support.  
+  which doesn't require the msdos filesystem support. 
 
   If you want to use umsdos, the Unix-like filesystem on top of DOS,
   which allows you to run Linux from within a DOS partition without
   repartitioning, you'll have to say Y or M here. If you have Windows
   95 or Windows NT installed on your MSDOS partitions, you should use
   the VFAT filesystem instead, or you will not be able to see the long
-  filenames generated by Windows 95 / Windows NT. 
+  filenames generated by Windows 95 / Windows NT.
 
-  This option will enlarge your kernel by about 7 kB. If unsure, say
-  Y. This will only work if you said Y to "fat fs support" as well. If
-  you want to compile this as a module however ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read Documentation/modules.txt. The module will be
-  called msdos.o.
+  This option will enlarge your kernel by about 7 kB. If unsure,
+  answer Y. This will only work if you said Y to "fat fs support" as
+  well. If you want to compile this as a module however ( = code which
+  can be inserted in and removed from the running kernel whenever you
+  want), say M here and read Documentation/modules.txt. The module
+  will be called msdos.o.
 
 vfat fs support
 CONFIG_VFAT_FS
   This allows you to mount MSDOS partitions of your hard drive. It
-  will let you use filenames in a way compatible with the long 
+  will let you use filenames in a way compatible with the long
   filenames used by Windows 95 and Windows NT fat-based (not NTFS)
   partitions. It does not support Windows 95 compressed filesystems.
   You cannot use the VFAT filesystem for your root partition; use
   UMSDOS instead. This option enlarges your kernel by about 10 kB and
-  it only works if you said Y to the "fat fs support" above. Please read
-  the file Documentation/filesystems/vfat.txt for details.
-  If unsure, say N. 
+  it only works if you said Y to the "fat fs support" above. Please
+  read the file Documentation/filesystems/vfat.txt for details. 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),
@@ -6335,7 +6542,7 @@ CONFIG_UMSDOS_FS
   backing everything up and restoring afterwards) and hence you're
   able to quickly try out Linux or show it to your friends; the
   disadvantage is that Linux becomes susceptible to DOS viruses and
-  that UMSDOS is somewhat slower than ext2fs.  Another use of umsdos
+  that UMSDOS is somewhat slower than ext2fs. Another use of umsdos
   is to write files with long unix filenames to MSDOS floppies; it
   also allows Unix-style softlinks and owner/permissions of files on
   MSDOS floppies. You will need a program called umssync in order to
@@ -6385,7 +6592,7 @@ CONFIG_NFS_FS
   ftp://sunsite.unc.edu/pub/Linux/docs/LDP, on its man page: "man
   nfs", and in the NFS-HOWTO.
   
-  An superior but less widely used alternative to NFS is provided by
+  A superior but less widely used alternative to NFS is provided by
   the Coda filesystem; see "Coda filesystem support" below.
 
   If you say Y here, you should have said Y to TCP/IP networking also.
@@ -6429,7 +6636,7 @@ CONFIG_NFSD
   You will need the support software from the linux-nfs package
   available at ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/.
   Please read the NFS-HOWTO, available via FTP (user: anonymous) from
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO. 
+  ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. 
 
   The NFS server is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -6439,8 +6646,8 @@ CONFIG_NFSD
 Emulate Sun NFS daemon
 CONFIG_NFSD_SUN
   If you would like for the server to allow clients to access
-  directories that are mountpoints on the local filesystem (this is
-  how nfsd behaves on Sun systems), say yes here.  If unsure, say N.
+  directories that are mount points on the local filesystem (this is
+  how nfsd behaves on Sun systems), say yes here. If unsure, say N.
 
 OS/2 HPFS filesystem support (read only)
 CONFIG_HPFS_FS
@@ -6472,7 +6679,7 @@ CONFIG_NTFS_FS
 NTFS read-write support (experimental)
 CONFIG_NTFS_RW
   If you say Y here, you will (hopefully) be able to write to NTFS
-  file systems as well as read from them.  The read-write support
+  file systems as well as read from them. The read-write support
   in NTFS is far from being complete and is not well tested. If you
   enable this, back up your NTFS volume first since it may get
   damaged.
@@ -6482,34 +6689,36 @@ CONFIG_NTFS_RW
 System V and Coherent filesystem support
 CONFIG_SYSV_FS
   SCO, Xenix and Coherent are commercial Unix systems for Intel
-  machines. Saying Y here would allow you to read and write to and
-  from their floppies and hard disk partitions. 
+  machines. Saying Y here would allow you to read to and write from
+  their floppies and hard disk partitions.
 
-  If you have a floppy or hard disk partition like that, it is likely
+  If you have floppies or hard disk partitions like that, it is likely
   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, UnixWare, Dell Unix and System V programs under
-  Linux and is often needed to run commercial software that's only
-  available for those systems. It's available via FTP (user:
-  anonymous) from ftp://tsx-11.mit.edu/pub/linux/BETA).
+  to run these binaries, you will want to install iBCS2 (Intel Binary
+  Compatibility Standard is a kernel module which lets you run SCO,
+  Xenix, Wyse, UnixWare, Dell Unix and System V programs under Linux
+  and is often needed to run commercial software that's only available
+  for those systems. It's available via FTP (user: anonymous) from
+  ftp://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 the System V filesystem support
-  (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 and directories between unixes (and even
-  other operating systems) is given by the tar program ("man tar" or
-  preferably "info tar"). Note also that this option has nothing
-  whatsoever to do 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. 
+  (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 and directories between unixes
+  (and even other operating systems) is given by the tar program ("man
+  tar" or preferably "info tar"). Note also that this option has
+  nothing whatsoever to do with the option "System V IPC". Read about
+  the System V filesystem in Documentation/filesystems/sysv-fs.txt.
+  Saying Y here 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. The module will be
-  called sysv.o. If you haven't heard about all of this before, it's
-  safe to say N.
+  called sysv.o. 
+
+  If you haven't heard about all of this before, it's safe to say N.
 
 Amiga FFS filesystem support
 CONFIG_AFFS_FS
@@ -6558,8 +6767,8 @@ CONFIG_ROMFS_FS
   want). The module is called romfs.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt. 
 
-  If you don't know whether you need it, then you don't need it: say
-  N.
+  If you don't know whether you need it, then you don't need it:
+  answer N.
 
 QNX filesystem support (EXPERIMENTAL)
 CONFIG_QNX4FS_FS  
@@ -6576,13 +6785,13 @@ CONFIG_QNX4FS_FS
 Kernel automounter support
 CONFIG_AUTOFS_FS
   The automounter is a tool to automatically mount remote filesystems
-  on demand.  This implementation is partially kernel-based to reduce
+  on demand. This implementation is partially kernel-based to reduce
   overhead in the already-mounted case; this is unlike the BSD
   automounter (amd), which is a pure user space daemon.
 
   To use the automounter you need the user-space tools from
-  ftp://ftp.kernel.org/pub/linux/daemons/autofs; you also want to say
-  Y to "NFS filesystem support", above.
+  ftp://ftp.kernel.org/pub/linux/daemons/autofs; you also want to
+  answer Y to "NFS filesystem support", above.
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -6597,8 +6806,8 @@ CONFIG_UFS_FS
   BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
   OpenBSD and NeXTstep) use a filesystem called UFS. Some System V
   Unixes can create and mount hard disk partitions and diskettes using
-  this filesystem as well. Saying Y here allows you to mount these
-  partitions and diskettes.
+  this filesystem as well. Saying Y here will allow you to read from
+  and write to these partitions and diskettes.
 
   If you only intend to mount files from some other Unix over the
   network using NFS, you don't need the UFS filesystem support (but
@@ -6699,12 +6908,12 @@ CONFIG_MAC_PARTITION
 SMB filesystem support (to mount WfW shares etc..)
 CONFIG_SMB_FS
   SMB (Server Message Block) is the protocol Windows for Workgroups
-  (WfW), Windows 95, Windows NT and Lan Manager use to share files and
-  printers over local networks. Saying Y here allows you to mount
-  their filesystems (often called "shares" in this context) and access
-  them just like any other Unix directory. Currently, this works only
-  if the Windows machines use TCP/IP as the underlying transport
-  protocol, and not NetBEUI. For details, read
+  (WfW), Windows 95, Windows NT and OS/2 Lan Manager use to share
+  files and printers over local networks. Saying Y here allows you to
+  mount their filesystems (often called "shares" in this context) and
+  access them just like any other Unix directory. Currently, this
+  works only if the Windows machines use TCP/IP as the underlying
+  transport protocol, and not NetBEUI. For details, read
   Documentation/filesystems/smbfs.txt and the SMB-HOWTO, available via
   FTP (user: anonymous) from
   ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
@@ -6738,18 +6947,17 @@ CONFIG_CODA_FS
   enables you to mount filesystems of a remote server and access them
   with regular Unix commands as if they were sitting on your hard
   disk. Coda has several advantages over NFS: support for disconnected
-  operation for laptops, read/write server replication, security model
-  for authentication and encryption, persistent client caches and
-  write back caching.
+  operation (e.g. for laptops), read/write server replication,
+  security model for authentication and encryption, persistent client
+  caches and write back caching.
 
   If you say Y here, your Linux box will be able to act as a Coda
   *client*. You will need user level code as well, both for the client
   and server. Servers are currently user level, i.e. need no kernel
-  support. For technical information, read
-  Documentation/filesystems/coda.txt. For further information see
-  http://www.coda.cs.cmu.edu (to browse the WWW, you need to have
-  access to a machine on the Internet that has a program like lynx or
-  netscape) or contact Peter Braam <braam@cs.cmu.edu>.
+  support. Please read Documentation/filesystems/coda.txt and check
+  out the Coda home page http://www.coda.cs.cmu.edu (to browse the
+  WWW, you need to have access to a machine on the Internet that has a
+  program like lynx or netscape).
 
   If you want to compile the coda client support as a module ( = code
   which can be inserted in and removed from the running kernel
@@ -6764,7 +6972,7 @@ CONFIG_NCP_FS
   mount NetWare file server volumes and to access them just like any
   other Unix directory. For details, please read the file
   Documentation/filesystems/ncpfs.txt in the kernel source and the
-  IPX-HOWTO on sunsite.unc.edu:/pub/Linux/docs/howto.
+  IPX-HOWTO on ftp://sunsite.unc.edu:/pub/Linux/docs/howto.
 
   You do not have to say Y here if you want your Linux box to act as a
   file *server* for Novell NetWare clients.
@@ -6887,16 +7095,17 @@ CONFIG_NLS_CODEPAGE_775
 nls codepage 850
 CONFIG_NLS_CODEPAGE_850
   The Microsoft fat filesystem family can deal with filenames in
-  native language character sets. These character sets are stored
-  in so-called DOS codepages. You need to include the appropriate
+  native language character sets. These character sets are stored in
+  so-called DOS codepages. You need to include the appropriate
   codepage if you want to be able to read/write these filenames on
   DOS/Windows partitions correctly. This does apply to the filenames
   only, not to the file contents. You can include several codepages;
   say Y here if you want to include the DOS codepage that is used for
-  much of Europe -- United Kingdom, Germany, Spain, Italy, and [add more
-  countries here]. It has some characters useful to many European
-  languages that are not part of the US codepage 437. If unsure, say
-  Y.
+  much of Europe -- United Kingdom, Germany, Spain, Italy, and [add
+  more countries here]. It has some characters useful to many European
+  languages that are not part of the US codepage 437. 
+
+  If unsure, say Y.
 
 nls codepage 852
 CONFIG_NLS_CODEPAGE_852
@@ -6907,7 +7116,7 @@ CONFIG_NLS_CODEPAGE_852
   DOS/Windows partitions correctly. This does apply to the filenames
   only, not to the file contents. You can include several codepages;
   say Y here if you want to include the Latin 2 codepage used by DOS
-  for much of Central and Eastern Europe.  It has all the required
+  for much of Central and Eastern Europe. It has all the required
   characters for these languages: Albanian, Croatian, Czech, English,
   Finnish, Hungarian, Irish, German, Polish, Romanian, Serbian (Latin
   transcription), Slovak, Slovenian, and Sorbian.
@@ -7075,7 +7284,7 @@ CONFIG_NLS_ISO8859_5
   correctly on the screen, you need to include the appropriate
   input/output character sets. Say Y here for ISO8859-5, a Cyrillic
   character set with which you can type Bulgarian, Byelorussian,
-  Macedonian, Russian, Serbian, and Ukrainian.  Note that the charset
+  Macedonian, Russian, Serbian, and Ukrainian. Note that the charset
   KOI8-R is preferred in Russia.
 
 nls iso8859-6
@@ -7131,30 +7340,67 @@ CONFIG_NLS_KOI8_R
 
 Virtual terminal
 CONFIG_VT
-  If you say Y here, you will get support for a terminal device with
+  If you say Y here, you will get support for terminal devices with
   display and keyboard devices. These are called "virtual" because you
-  can run several virtual terminals on one physical terminal; however,
-  you need at least one virtual terminal device in order to make use
-  of a physical terminal. Only people using embedded systems want to
-  say N here; most everybody else says Y. If unsure, say Y, or else
-  you won't be able to do much with your new shiny Linux system :-)
+  can run several virtual terminals (also called virtual consoles) on
+  one physical terminal. This is rather useful, for example one
+  virtual terminal can collect system messages and warnings, another
+  one can be used for a text-mode user session, and a third could run
+  an X session, all in parallel. Switching between virtual terminals
+  is done with certain key combinations, usually Alt-<function key>.
+
+  The setterm command ("man setterm") can be used to change the
+  properties (such as colors) of a virtual terminal.
+
+  You need at least one virtual terminal device in order to make use
+  of your keyboard and monitor. Therefore, only people configuring an
+  embedded system would want to say N here in order to save some
+  memory; the only way to log into such a system is then via a serial
+  or network connection.
+
+  If unsure, say Y, or else you won't be able to do much with your new
+  shiny Linux system :-)
 
 Support for console on virtual terminal
 CONFIG_VT_CONSOLE
-  If you say Y here, by default all kernel messages will be sent to
-  the device /dev/tty0 which corresponds to the virtual terminal that
-  is visible on your display. You should say Y here unless you only
-  want to have the kernel messages output to a serial port (in which
-  case you probably want to say Y to "Console on serial port", below).
+  The system console is the device which receives all kernel messages
+  and warnings and which allows logins in single user mode. If you
+  answer Y here, a virtual terminal (the device used to interact with
+  a physical terminal) can be used as system console. This is the most
+  common mode of operations, so you should say Y here unless you want
+  the kernel messages be output only to a serial port (in which case
+  you should say Y to "Console on serial port", below).
+
+  If you do say Y here, by default the currently visible virtual
+  terminal (/dev/tty0) will be used as system console. You can change
+  that with a kernel command line option such as "console=tty3" which
+  would use the third virtual terminal as system console. (Try "man
+  bootparam" or see the documentation of your boot loader (lilo or
+  loadlin) about how to pass options to the kernel at boot time. The
+  lilo procedure is also explained in the SCSI-HOWTO, available via
+  FTP (user: anonymous) in
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.)
+
+  If unsure, say Y.
 
 Software generated cursor
 CONFIG_SOFTCURSOR
   If you say Y here, you'll be able to do lots of nice things with the
   cursors of your virtual consoles -- for example turn them into
   non-blinking block cursors which are more visible on laptop screens,
-  or change their color depending on the virtual console you're on.
+  or change their colors depending on the virtual console they're on.
   See Documentation/VGA-softcursor.txt for more information.
 
+Support for PowerMac keyboard
+CONFIG_MAC_KEYBOARD
+  This option allows you to use an ADB keyboard attached to your
+  machine. Note that this disables any other (ie. PS/2) keyboard
+  support, even if your machine is physically capable of using both at
+  the same time.
+  
+  If you use an ADB keyboard (4 pin connector), say Y here.
+  If you use a PS/2 keyboard (6 pin connector), say N here.
+
 Standard/generic serial support
 CONFIG_SERIAL
   This selects whether you want to include the driver for the standard
@@ -7169,38 +7415,54 @@ CONFIG_SERIAL
   Documentation/modules.txt. The module will be called serial.o.
   [WARNING: Do not compile this driver as a module if you are using
   non-standard serial ports, since the configuration information will
-  be lost if you unload the driver. This limitation may be lifted in
-  the future.]
+  be lost when the driver is unloaded. This limitation may be lifted
+  in the future.]
 
   BTW1: If you have a mouseman serial mouse which is not recognized by
   the X window system, try running gpm first. 
   
   BTW2: If you intend to connect a so-called Winmodem to your
-  machine's serial port, forget it. These modems require proprietary
-  drivers which are only available under Windows.
+  machine's serial port, forget it. These modems are crippled and
+  require proprietary drivers which are only available under Windows.
 
   Most people will say Y or M here, so that they can use serial mice,
   modems and similar devices connecting to the standard serial ports.
 
 Support for console on serial port
 CONFIG_SERIAL_CONSOLE
-  If you say Y here, it is possible to use a serial port as the
-  console. By default still the currently visible virtual console will
-  be used as the system console but you can alter that using a kernel
-  command line option such as "console=ttyS1". (Try "man bootparam" or
-  see the documentation of your boot loader (lilo or loadlin) about
-  how to pass options to the kernel at boot time. The lilo procedure
-  is also explained in the SCSI-HOWTO, available via FTP (user:
-  anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.) If you
-  don't have a VGA card installed and you say Y here, the kernel will
-  automatically use /dev/ttyS0 as system console.
+  If you say Y here, it will be possible to use a serial port as the
+  system console (the system console is the device which receives all
+  kernel messages and warnings and which allows logins in single user
+  mode). This could be useful if some terminal or printer is connected
+  to that serial port.
+
+  Even if you say Y here, the currently visible virtual console
+  (/dev/tty0) will still be used as the system console by default, but
+  you can alter that using a kernel command line option such as
+  "console=ttyS1". (Try "man bootparam" or see the documentation of
+  your boot loader (lilo or loadlin) about how to pass options to the
+  kernel at boot time. The lilo procedure is also explained in the
+  SCSI-HOWTO, available via FTP (user: anonymous) in
+  ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.) 
+
+  If you don't have a VGA card installed and you say Y here, the
+  kernel will automatically use the first serial line, /dev/ttyS0, as
+  system console.
+
+  If unsure, say N.
+
+Support for PowerMac serial ports
+CONFIG_MAC_SERIAL
+  If you have Macintosh style serial ports (8 pin mini-DIN), say Y
+  here. If you also have regular serial ports and enable the driver
+  for them, you can't currently use the serial console feature.
 
 Comtrol Rocketport support
 CONFIG_ROCKETPORT
   This is a driver for the Comtrol Rocketport cards which provide
-  multiple 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. 
+  multiple 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 dial-in server.
 
   If you want to compile this driver as a module, say M here and read
   Documentation/modules.txt. The module will be called rocket.o.
@@ -7208,12 +7470,12 @@ CONFIG_ROCKETPORT
 Digiboard Intelligent async support
 CONFIG_DIGIEPCA
   This is a driver for Digi International's Xx, Xeve, and Xem series
-  of cards which provide multiple serial ports.  You would need
+  of cards which provide multiple 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. This driver supports the
-  original PC (ISA) boards as well as PCI, and EISA.  If you have a
-  card like this, say Y here and read the file
-  Documentation/digiepca.txt.  
+  box, for instance in order to become a dial-in server. This driver
+  supports the original PC (ISA) boards as well as PCI, and EISA. If
+  you have a card like this, say Y here and read the file
+  Documentation/digiepca.txt.
 
   NOTE: There is another, separate driver for the Digiboard PC boards:
   "Digiboard PC/Xx Support" below. You should (and can) only select
@@ -7227,8 +7489,8 @@ CONFIG_DIGI
   This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards
   that give 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 have a card like that, say Y here and
-  read the file Documentation/digiboard.txt. 
+  order to become a dial-in server. If you have a card like that, say
+  Y here and read the file Documentation/digiboard.txt.
 
   If you want to compile this driver as a module, say M here and read
   Documentation/modules.txt. The module will be called pcxx.o.
@@ -7238,8 +7500,8 @@ CONFIG_RISCOM8
   This is a driver for the SDL Communications RISCom/8 multiport 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 have a card like that, say Y here
-  and read the file Documentation/riscom8.txt. 
+  in order to become a dial-in server. If you have a card like that,
+  say Y here and read the file Documentation/riscom8.txt.
 
   Also it's possible to say M here and compile this driver as kernel
   loadable module; the module will be called riscom8.o.
@@ -7249,7 +7511,7 @@ CONFIG_SPECIALIX
   This is a driver for the Specialix IO8+ multiport card (both the
   ISA and the PCI version) 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. 
+  your Linux box, for instance in order to become a dial-in server.
 
   If you have a card like that, say Y here and read the file
   Documentation/specialix.txt. Also it's possible to say M here and
@@ -7258,19 +7520,19 @@ CONFIG_SPECIALIX
 
 Specialix DTR/RTS pin is RTS
 CONFIG_SPECIALIX_RTSCTS
-  The Specialix card can only support either RTS or DTR. If you say
-  here, the driver will use the pin as "DTR" when the tty is in
-  software handshake mode. If you say Y here or hardware handshake
-  is on, it will always be RTS. Read the file
-  Documentation/specialix.txt for more information.
+  The Specialix card can only support either RTS or DTR. If you say N
+  here, the driver will use the pin as "DTR" when the tty is in
+  software handshake mode. If you say Y here or hardware handshake is
+  on, it will always be RTS. Read the file Documentation/specialix.txt
+  for more information.
 
 Cyclades async mux support
 CONFIG_CYCLADES
   This is a driver for a card that 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. For
-  information about the Cyclades-Z card, read
-  drivers/char/README.cycladesZ. 
+  your Linux box, for instance in order to become a dial-in server.
+  For information about the Cyclades-Z card, read
+  drivers/char/README.cycladesZ.
 
   As of 1.3.9x kernels, this driver's minor numbers start at 0 instead
   of 32.
@@ -7286,10 +7548,10 @@ Stallion multiport serial support
 CONFIG_STALDRV
   Stallion cards give 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 say Y here, you will be
-  asked for your specific card model in the next questions. Make sure
-  to read drivers/char/README.stallion in this case. If you have never
-  heard about all this, it's safe to say N.
+  instance in order to become a dial-in server. If you say Y here, you
+  will be asked for your specific card model in the next questions.
+  Make sure to read drivers/char/README.stallion in this case. If you
+  have never heard about all this, it's safe to say N.
 
 Stallion EasyIO or EC8/32 support 
 CONFIG_STALLION
@@ -7315,8 +7577,8 @@ CONFIG_ISTALLION
 
 Hayes ESP serial port support
 CONFIG_ESPSERIAL
-  This is a driver which supports Hayes ESP serial ports.  Both single
-  port cards and multiport cards are supported.  Make sure to read
+  This is a driver which supports Hayes ESP serial ports. Both single
+  port cards and multiport cards are supported. Make sure to read
   Documentation/hayes-esp.txt. 
 
   To compile this driver as a module ( = code which can be inserted in
@@ -7346,8 +7608,9 @@ CONFIG_UNIX98_PTYS
   filesystem; therefore, if you say Y here you should say Y to
   "/dev/pts filesystem for Unix98 PTYs" as well.
 
-  Say Y here if you are uncertain, unless you are very short on
-  memory.
+  You should say Y here only if your C library is glibc 2.1 or later
+  (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). Read the
+  instructions in Documentation/Changes.
 
 Maximum number of Unix98 PTYs in use (0-2048)
 CONFIG_UNIX98_PTY_COUNT
@@ -7358,7 +7621,7 @@ CONFIG_UNIX98_PTY_COUNT
   connection and every xterm uses up one PTY.
 
   When not in use, each additional set of 256 PTYs occupy
-  approximately 8K of kernel memory on 32-bit architectures.
+  approximately 8 KB of kernel memory on 32-bit architectures.
 
 Parallel printer support
 CONFIG_PRINTER
@@ -7392,7 +7655,7 @@ Support IEEE1284 status readback
 CONFIG_PRINTER_READBACK
   If your printer conforms to IEEE 1284, it may be able to provide a
   status indication when you read from it (for example, with `cat
-  /dev/lp1').  To use this feature, say Y here.
+  /dev/lp1'). To use this feature, say Y here.
 
 Mouse Support (not serial mice)
 CONFIG_MOUSE
@@ -7436,20 +7699,16 @@ CONFIG_PSMOUSE
   AST and IBM all use this as their mouse port on currently shipping
   machines. The trackballs of some laptops are PS/2 mice also. In
   particular, the C&T 82C710 mouse on TI Travelmates is a PS/2 mouse.
+
   Although PS/2 mice are not technically bus mice, they are explained
   in detail in the Busmouse-HOWTO, available via FTP (user: anonymous)
-  in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. When using a PS/2
-  mouse, you can get problems if you want to use the mouse both on the
-  Linux console and under X. Using the "-R" option of the Linux mouse
-  managing program gpm (available from
-  sunsite.unc.edu:/pub/Linux/system/Daemons) solves this problem, or
-  you can get the "mconv" utility also from sunsite.
-
-  If you want to compile this mouse 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. The module
-  will be called psaux.o. If you are unsure, say N and read the HOWTO
-  nevertheless: it will tell you what you have.
+  in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. 
+
+  When using a PS/2 mouse, you can get problems if you want to use the
+  mouse both on the Linux console and under X. Using the "-R" option
+  of the Linux mouse managing program gpm (available from
+  ftp://sunsite.unc.edu:/pub/Linux/system/Daemons) solves this
+  problem, or you can get the "mconv" utility also from sunsite.
 
 C&T 82C710 mouse port support (as on TI Travelmate)
 CONFIG_82C710_MOUSE
@@ -7464,7 +7723,7 @@ CONFIG_PC110_PAD
   http://toy.cabi.net; to browse the WWW, you need to have access to a
   machine on the Internet that has a program like lynx or
   netscape). It can turn the digitizer pad into a PS/2 mouse emulation
-  with tap gestures or into an absolute pad.  
+  with tap gestures or into an absolute pad. 
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -7503,13 +7762,10 @@ CONFIG_ATIXL_BUSMOUSE
   If you are unsure, say N and read the HOWTO nevertheless: it will
   tell you what you have.
 
-Support for user miscellaneous modules
-CONFIG_UMISC
-  This option forces generic miscellaneous minor device support in the
-  kernel, and allows later loading of user miscellaneous character
-  device modules, such as drivers for optic pens and touchscreens.
-  Unless you need such specific modules, or are willing to write/test
-  one, just say N.
+Support for PowerMac ADB mouse
+CONFIG_ADBMOUSE
+  If you have an ADB mouse (4 pin connector) as is common on
+  Macintoshes, say Y here.
 
 QIC-02 tape support
 CONFIG_QIC02_TAPE
@@ -7525,7 +7781,7 @@ CONFIG_QIC02_DYNCONF
   header file (include/linux/tpqic02.h), in which case you should
   say N, or you can fetch a program via anonymous FTP which is able
   to configure this driver during runtime. The program to do this is
-  called 'qic02conf' and it is part of the 'tpqic02-support-X.Y.tar.gz'
+  called 'qic02conf' and it is part of the tpqic02-support-X.Y.tar.gz
   support package.
 
   If you want to use the qic02conf program, say Y.
@@ -7607,7 +7863,7 @@ CONFIG_ZFTAPE
 
 Default block size for zftape
 CONFIG_ZFT_DFLT_BLK_SZ
-  If unsure leave this at its default value, i.e. 10240.  Note that
+  If unsure leave this at its default value, i.e. 10240. Note that
   you specify only the default block size here. The block size can be
   changed at run time using the MTSETBLK tape operation with the
   MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the
@@ -7618,7 +7874,7 @@ CONFIG_ZFT_DFLT_BLK_SZ
   in multiples of a fixed block size. The block size defaults to
   10240 which is what GNU tar uses. The values for the block size
   should be either 1 or multiples of 1024 up to a maximum value of
-  63488 (i.e. 62k). If you specify `1' then zftape's builtin
+  63488 (i.e. 62 K). If you specify `1' then zftape's builtin
   compression will be disabled.
 
   Reasonable values are `10240' (GNU tar's default block size),
@@ -7628,12 +7884,12 @@ CONFIG_ZFT_DFLT_BLK_SZ
 
 Number of DMA buffers
 CONFIG_FT_NR_BUFFERS
-  Please leave this at `3' unless you REALLY know what you are
-  doing. It is not necessary to change this value. Values below 3 make
-  the proper use of ftape impossible, values greater than 3 are a waste
-  of memory. You can change the amount of DMA memory used by ftape at
+  Please leave this at `3' unless you REALLY know what you are doing.
+  It is not necessary to change this value. Values below 3 make the
+  proper use of ftape impossible, values greater than 3 are a waste of
+  memory. You can change the amount of DMA memory used by ftape at
   runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer
-  wastes 32kb of memory. Please note that this memory cannot be
+  wastes 32 KB of memory. Please note that this memory cannot be
   swapped out.
 
 Procfs entry for ftape
@@ -7646,9 +7902,9 @@ CONFIG_FT_PROC_FS
   cartridge, the kernel driver, your tape drive, the floppy disk
   controller and the error history for the most recent use of the
   kernel driver. Saying Y will enlarge the size of the ftape driver
-  by approximately 2k.
+  by approximately 2 KB.
 
-  WARNING: When compiling ftape as a module (i.e. saying `M' to
+  WARNING: When compiling ftape as a module (i.e. saying M to
   "Floppy tape drive") it is dangerous to use ftape's proc file system
   interface. Accessing `/proc/ftape' while the module is unloaded will
   result in a kernel Oops. This cannot be fixed from inside ftape.
@@ -7762,9 +8018,9 @@ CONFIG_FT_FDC_IRQ
 
   Note that this menu lets you specify only the default setting for
   the IRQ channel. The hardware configuration can be changed at boot
-  time (when ftape is compiled into the kernel, i.e. if you specified
-  Y to "Floppy tape drive") or module load time (i.e. if you have said M
-  to "Floppy tape drive").
+  time (when ftape is compiled into the kernel, i.e. if you said Y to
+  "Floppy tape drive") or module load time (i.e. if you said M to
+  "Floppy tape drive").
 
   Please read also the file Documentation/ftape.txt which contains a
   short description of the parameters that can be set at boot or load
@@ -7788,9 +8044,9 @@ CONFIG_FT_FDC_DMA
 
   Note that this menu lets you specify only the default setting for
   the DMA channel. The hardware configuration can be changed at boot
-  time (when ftape is compiled into the kernel, i.e. if you specified
-  Y to "Floppy tape drive") or module load time (i.e. if you have said M
-  to "Floppy tape drive").
+  time (when ftape is compiled into the kernel, i.e. if you said Y to
+  "Floppy tape drive") or module load time (i.e. if you said M to
+  "Floppy tape drive").
 
   Please read also the file Documentation/ftape.txt which contains a
   short description of the parameters that can be set at boot or load
@@ -7828,11 +8084,11 @@ CONFIG_MTRR
   PCI or AGP bus. Enabling write-combining allows bus write transfers
   to be combined into a larger transfer before bursting over the
   PCI/AGP bus. This can increase performance of image write operations
-  2.5 times or more.
-  This option creates a /proc/mtrr file which may be used to manipulate
-  your MTRRs. Typically the X server should use this. This should have
-  a reasonably generic interface so that similar control registers on
-  other processors can be easily supported.
+  2.5 times or more. This option creates a /proc/mtrr file which may
+  be used to manipulate your MTRRs. Typically the X server should use
+  this. This should have a reasonably generic interface so that
+  similar control registers on other processors can be easily
+  supported.
 
   Saying Y here also fixes a problem with buggy SMP BIOSes which only
   set the MTRRs for the boot CPU and not the secondary CPUs. This can
@@ -7841,7 +8097,8 @@ CONFIG_MTRR
   In general you should compile this into the kernel, rather than as a
   loadable module, because the BIOS fix needs to be done early in the
   boot sequence. If you compile this as a module, the BIOS fix will be
-  delayed until when you load the module. You do this at your own risk.
+  delayed until when you load the module. You do this at your own
+  risk.
 
   See Documentation/mtrr.txt for more information.
 
@@ -7853,8 +8110,8 @@ CONFIG_FT_ALPHA_CLOCK
 
 Zilog serial support
 CONFIG_SUN_ZS
-  This driver does not exist at this point, so you might as well say
-  N.
+  This driver does not exist at this point, so you might as well 
+  say N.
 
 Advanced Power Management
 CONFIG_APM
@@ -7892,41 +8149,45 @@ CONFIG_APM
   anything, try disabling/enabling this option (or disabling/enabling
   APM in your BIOS). 
 
-  Some other things to try when experiencing seemingly random, "weird"
-  problems:
-   1) passing the "no-hlt" option to the kernel 
-   2) switching on floating point emulation in the kernel and passing
+  Some other things you should try when experiencing seemingly random,
+  "weird" problems:
+
+   1) make sure that you have enough swap space and that it is
+      enabled. 
+   2) pass the "no-hlt" option to the kernel 
+   3) switch on floating point emulation in the kernel and pass
       the "no387" option to the kernel
-   3) passing the "floppy=nodma" option to the kernel
-   4) passing the "mem=4M" option to the kernel (thereby disabling 
-      all but the first 4M of RAM)
-   5) making sure that the CPU is not over clocked.
-   6) reading the sig11 FAQ at http://www.bitwizard.nl/sig11/
-   7) disabling the cache from your BIOS settings
-   8) installing a better fan
-   9) exchanging RAM chips 
-   10) exchanging the motherboard.
+   4) pass the "floppy=nodma" option to the kernel
+   5) pass the "mem=4M" option to the kernel (thereby disabling 
+      all but the first 4 MB of RAM)
+   6) make sure that the CPU is not over clocked.
+   7) read the sig11 FAQ at http://www.bitwizard.nl/sig11/
+   8) disable the cache from your BIOS settings
+   9) install a fan for the video card or exchange video RAM
+   10) install a better fan for the CPU
+   11) exchange RAM chips 
+   12) exchange the motherboard.
 
 Ignore USER SUSPEND
 CONFIG_APM_IGNORE_USER_SUSPEND
-  This option will ignore USER SUSPEND requests.  On machines with a
-  compliant APM BIOS, you want to say N.  However, on the NEC Versa M
+  This option will ignore USER SUSPEND requests. On machines with a
+  compliant APM BIOS, you want to say N. However, on the NEC Versa M
   series notebooks, it is necessary to say Y because of a BIOS bug.
 
 Enable APM at boot time
 CONFIG_APM_DO_ENABLE
-  Enable APM features at boot time.  From page 36 of the APM BIOS
+  Enable APM features at boot time. From page 36 of the APM BIOS
   specification: "When disabled, the APM BIOS does not automatically
   power manage devices, enter the Standby State, enter the Suspend
   State, or take power saving steps in response to CPU Idle calls."
   This driver will make CPU Idle calls when Linux is idle (unless this
-  feature is turned off -- see "Do CPU IDLE calls", below).  This
+  feature is turned off -- see "Do CPU IDLE calls", below). This
   should always save battery power, but more complicated APM features
-  will be dependent on your BIOS implementation.  You may need to turn
+  will be dependent on your BIOS implementation. You may need to turn
   this option off if your computer hangs at boot time when using APM
-  support, or if it beeps continuously instead of suspending.  Turn
+  support, or if it beeps continuously instead of suspending. Turn
   this off if you have a NEC UltraLite Versa 33/C or a Toshiba
-  T400CDT.  This is off by default since most machines do fine without
+  T400CDT. This is off by default since most machines do fine without
   this feature.
 
 Do CPU IDLE calls
@@ -7941,12 +8202,12 @@ CONFIG_APM_CPU_IDLE
 
 Enable console blanking using APM
 CONFIG_APM_DISPLAY_BLANK
-  Enable console blanking using the APM.  Some laptops can use this to
+  Enable console blanking using the APM. Some laptops can use this to
   turn off the LCD backlight when the screen blanker of the Linux
-  virtual console blanks the screen.  Note that this is only used by
+  virtual console blanks the screen. Note that this is only used by
   the virtual console screen blanker, and won't turn off the backlight
   when using the X Window system. This also doesn't have anything to
-  do with your VESA-compliant power-saving monitor.  Further, this
+  do with your VESA-compliant power-saving monitor. Further, this
   option doesn't work for all laptops -- it might not turn off your
   backlight at all, or it might print a lot of errors to the console,
   especially if you are using gpm.
@@ -7954,13 +8215,14 @@ CONFIG_APM_DISPLAY_BLANK
 Power off on shutdown 
 CONFIG_APM_POWER_OFF
   Enable the ability to power off the computer after the Linux kernel
-  is halted.  You will need software (e.g., a suitable version of the
+  is halted. You will need software (e.g., a suitable version of the
   halt(8) command ("man 8 halt")) to cause the computer to power down.
   Recent versions of the sysvinit package available from
   ftp://sunsite.unc.edu/pub/Linux/system/daemons/init/ (user:
   anonymous) contain support for this ("halt -p" shuts down Linux and
-  powers off the computer).  As with the other APM options, this
-  option may not work reliably with some APM BIOS implementations.
+  powers off the computer, if executed from runlevel 0). As with the
+  other APM options, this option may not work reliably with some APM
+  BIOS implementations.
 
 Ignore multiple suspend/standby events
 CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
@@ -7985,8 +8247,8 @@ CONFIG_WATCHDOG
   your computer. For details, read Documentation/watchdog.txt in the
   kernel source.
 
-  The watchdog is usually used together with the watchdog daemon which
-  is available via FTP (user: anonymous) from
+  The watchdog is usually used together with the watchdog daemon 
+  which is available via FTP (user: anonymous) from
   ftp://tsx-11.mit.edu/pub/linux/sources/sbin/. This daemon can also
   monitor NFS connections and can reboot the machine when the process
   table is full.
@@ -8043,7 +8305,7 @@ CONFIG_PCWATCHDOG
   This is the driver for the Berkshire Products PC Watchdog card.
   This card simply watches your kernel to make sure it doesn't freeze,
   and if it does, it reboots your computer after a certain amount of
-  time.  This driver is like the WDT501 driver but for different
+  time. This driver is like the WDT501 driver but for different
   hardware. Please read Documentation/pcwd-watchdog.txt. The PC
   watchdog cards can be ordered from http://www.berkprod.com. Some
   example rc.local files are available from ftp://ftp.bitgate.com. 
@@ -8051,8 +8313,9 @@ CONFIG_PCWATCHDOG
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module is called pcwd.o. If you want to compile it as a module,
-  say M here and read Documentation/modules.txt. Most people will say
-  N.
+  say M here and read Documentation/modules.txt. 
+
+  Most people will say N.
 
 Acquire SBC Watchdog Timer
 CONFIG_ACQUIRE_WDT
@@ -8062,54 +8325,55 @@ CONFIG_ACQUIRE_WDT
   it does, it reboots your computer after a certain amount of time.
 
   This driver is like the WDT501 driver but for different hardware.
-  This driver is also available as a module ( = code which can be 
+  This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
-  The module is called pscwdt.o. If you want to compile it as a module,
-  say M here and read Documentation/modules.txt.  Most people will say N.
+  The module is called pscwdt.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt. Most people
+  will say N.
 
 Enhanced Real Time Clock Support
 CONFIG_RTC
   If you say Y here and create a character special file /dev/rtc with
   major number 10 and minor number 135 using mknod ("man mknod"), you
-  will get access to the real time clock built into your
-  computer. Every PC has such a clock built in. It can be used to
-  generate signals from as low as 1Hz up to 8192Hz, and can also be
-  used as a 24 hour alarm.  It reports status information via the file
-  /proc/rtc and its behaviour is set by various ioctls on
-  /dev/rtc. 
-
-  People running SMP (= multiprocessor) versions of Linux should say Y
+  will get access to the real time clock built into your computer.
+  Every PC has such a clock built in. It can be used to generate
+  signals from as low as 1Hz up to 8192Hz, and can also be used as a
+  24 hour alarm. It reports status information via the file /proc/rtc
+  and its behaviour is set by various ioctls on /dev/rtc.
+
+  People running SMP (multiprocessor) versions of Linux should say Y
   here to read and set the RTC clock in a SMP compatible
   fashion. (They should also read Documentation/smp and
   Documentation/IO-APIC.txt and the SMP-FAQ on the WWW at
   http://www.irisa.fr/prive/mentre/smp-faq/ (to browse the WWW, you
   need to have access to a machine on the Internet that has a program
-  like lynx or netscape)).
+  like lynx or netscape).)
 
   If you think you have a use for such a device (such as periodic data
-  sampling), then say Y here, and go read the file
-  Documentation/rtc.txt for details.
+  sampling), then say Y here, and read Documentation/rtc.txt for
+  details.
 
 Tadpole ANA H8 Support
 CONFIG_H8
   The Hitachi H8/337 is a microcontroller used to deal with the power
   and thermal environment. If you say Y here, you will be able to
-  communicate with it via via a character special device. If unsure,
-  say N.
+  communicate with it via a character special device. 
+
+  If unsure, say N.
 
 /dev/nvram support
 CONFIG_NVRAM
   If you say Y here and create a character special file /dev/nvram
   with major number 10 and minor number 144 using mknod ("man mknod"),
-  you get access to the 50 bytes of non-volatile memory in the real
-  time clock (RTC), which is contained in every PC and most
-  Ataris. This memory is conventionally called "CMOS RAM" on PCs and
-  "NVRAM" on Ataris. /dev/nvram may be used to view settings there, or
-  to change them (with some utility). It could also be used to
-  frequently save a few bits of very important data that may not be
-  lost over power-off and for which writing to disk is too
-  insecure. On Atari machines, /dev/nvram is always configured and
-  does not need to be selected.  
+  you get read and write access to the 50 bytes of non-volatile memory
+  in the real time clock (RTC), which is contained in every PC and
+  most Ataris. This memory is conventionally called "CMOS RAM" on PCs
+  and "NVRAM" on Ataris. /dev/nvram may be used to view settings
+  there, or to change them (with some utility). It could also be used
+  to frequently save a few bits of very important data that may not be
+  lost over power-off and for which writing to disk is too insecure.
+  On Atari machines, /dev/nvram is always configured and does not need
+  to be selected.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -8121,7 +8385,7 @@ CONFIG_JOYSTICK
   If you have a joystick, you can say Y here to enable generic
   joystick support. You will also need to say Y or M to at least one
   of the hardware specific joystick drivers. This will make the
-  joysticks available under /dev/jsX devices. Please read the file
+  joysticks available as /dev/jsX devices. Please read the file
   Documentation/joystick.txt which contains more information and the
   location of the joystick package that you'll need.
 
@@ -8172,31 +8436,32 @@ CONFIG_JOY_SIDEWINDER
 
 ThrustMaster DirectConnect (BSP) joysticks
 CONFIG_JOY_THRUSTMASTER
-  Say Y here if you have a ThrustMaster Millenium 3D Inceptor, ThrustMaster
-  3D Rage Pad, or ThrustMaster WCS III. For more information on how to use the
-  driver please read Documentation/joystick.txt
+  Say Y here if you have a ThrustMaster Millenium 3D Inceptor,
+  ThrustMaster 3D Rage Pad, or ThrustMaster WCS III. For more
+  information on how to use the driver please read
+  Documentation/joystick.txt
 
 NES, SNES, PSX, Multisystem gamepads
 CONFIG_JOY_CONSOLE
   Say Y here if you have a Nintendo Entertainment System gamepad,
   Super Nintendo Entertainment System gamepad, Sony PlayStation
-  gamepad or a Multisystem - Atari, Amiga, Commodore, Amstrad CPC
+  gamepad or a Multisystem -- Atari, Amiga, Commodore, Amstrad CPC
   joystick. For more information on how to use the driver please read
   Documentation/joystick.txt
 
 Sega, Multisystem gamepads
 CONFIG_JOY_DB9
   Say Y here if you have a Sega Master System gamepad, Sega Genesis
-  gamepad, Sega Saturn gamepad, or a Multisystem - Atari, Amiga,
+  gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
   Commodore, Amstrad CPC joystick. For more information on how to use
   the driver please read Documentation/joystick.txt
 
 TurboGraFX Multisystem joystick interface
 CONFIG_JOY_TURBOGRAFX
-  Say Y here if you have the TurboGraFX interface by Steffen Schwenke, and
-  want to use it with Multiststem - Atari, Amiga, Commodore, Amstrad CPC
-  joystick. For more information on how to use the driver please read
-  Documentation/joystick-parport.txt
+  Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
+  and want to use it with Multiststem -- Atari, Amiga, Commodore,
+  Amstrad CPC joystick. For more information on how to use the driver
+  please read Documentation/joystick-parport.txt
 
 Amiga joysticks
 CONFIG_JOY_AMIGA
@@ -8207,13 +8472,13 @@ CONFIG_JOY_AMIGA
 Atomwide Serial Support
 CONFIG_ATOMWIDE_SERIAL
   If you have an Atomwide Serial card for an Acorn system, say Y to
-  this option.  The driver can handle 1, 2, or 3 port cards.
+  this option. The driver can handle 1, 2, or 3 port cards.
   If unsure, say N
 
 The Serial Port Dual Serial Port
 CONFIG_DUALSP_SERIAL
   If you have the Serial Port's dual serial card for an Acorn system,
-  say Y to this option.  If unsure, say N
+  say Y to this option. If unsure, say N
 
 Sound card support
 CONFIG_SOUND
@@ -8240,9 +8505,8 @@ CONFIG_SOUND
 
   I'm told that even without a sound card, you can make your computer
   say more than an occasional beep, by programming the PC speaker.
-  Kernel patches and programs to do that are in the pcsndrv package on
-  ftp://sunsite.unc.edu/pub/Linux/kernel/patches/console/ and in the
-  pcsp patch at http://www.imladris.demon.co.uk/pcsp/
+  Kernel patches and supporting utilities to do that are in the pcsp
+  package, available at http://www.imladris.demon.co.uk/pcsp/.
 
 OSS sound modules
 CONFIG_SOUND_OSS
@@ -8267,7 +8531,7 @@ CONFIG_SOUND_OPL3SA1
 ProAudioSpectrum 16 support
 CONFIG_SOUND_PAS
   Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
-  16 or Logitech SoundMan 16 sound card.  Don't answer Y if you have
+  16 or Logitech SoundMan 16 sound card. Don't answer Y if you have
   some other card made by Media Vision or Logitech since they are not
   PAS16 compatible.
 
@@ -8277,7 +8541,7 @@ CONFIG_SOUND_SB
   Creative Labs or a 100% hardware compatible clone (like the
   Thunderboard or SM Games). If your card was in the list of supported
   cards look at the card specific instructions in the
-  drivers/sound/Readme.cards file before answering this question.  For
+  drivers/sound/Readme.cards file before answering this question. For
   an unknown card you may answer Y if the card claims to be
   Sound Blaster-compatible. 
 
@@ -8330,12 +8594,17 @@ CONFIG_SOUND_MPU401
   instructions in the drivers/sound/Readme.cards file. It's safe to
   answer Y if you have a true MPU401 MIDI interface card.
 
-6850 UART Midi support
+6850 UART support
 CONFIG_SOUND_UART6850
   This option enables support for MIDI interfaces based on the 6850
-  UART chip. This interface is rarely found on sound cards.  It's safe
+  UART chip. This interface is rarely found on sound cards. It's safe
   to answer N to this question.
 
+VIDC Sound
+CONFIG_VIDC_SOUND
+  Say Y here for ARM systems with the VIDC video controller and 16-bit
+  Linear sound DACs. If unsure, say N.
+
 PSS (AD1848, ADSP-2115, ESC614) support
 CONFIG_SOUND_PSS
   Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven
@@ -8357,8 +8626,8 @@ CONFIG_PSS_MIXER
 
 Have DSPxxx.LD firmware file
 CONFIG_PSS_HAVE_BOOT
-  If you have the DSPxxx.LD file or SYNTH.LD file for you card, answer
-  to include this file. Without this file the synth device (OPL) may
+  If you have the DSPxxx.LD file or SYNTH.LD file for you card, say Y
+  to include this file. Without this file the synth device (OPL) may
   not work.
 
 Full pathname of DSPxxx.LD firmware file
@@ -8369,7 +8638,7 @@ CONFIG_PSS_BOOT_FILE
 16 bit sampling option of GUS (_NOT_ GUS MAX)
 CONFIG_SOUND_GUS16
   Answer Y if you have installed the 16 bit sampling daughtercard on
-  your GUS.  Answer N if you have a GUS MAX, since saying Y here
+  your GUS. Answer N if you have a GUS MAX, since saying Y here
   disables GUS MAX support.
 
 GUS MAX support
@@ -8378,10 +8647,10 @@ CONFIG_SOUND_GUSMAX
 
 Microsoft Sound System support
 CONFIG_SOUND_MSS
-  Again think carefully before answering Y to this question.  It's
-  safe to answer Y if you have the original Windows Sound System card
-  made by Microsoft or Aztech SG 16 Pro (or NX16 Pro).  Also you may
-  answer Y in case your card is NOT among these:
+  Again think carefully before answering Y to this question. It's safe
+  to answer Y if you have the original Windows Sound System card made
+  by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may say Y
+  in case your card is NOT among these:
 
      ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16,
      Ensoniq SoundScape (and compatibles made by Reveal and Spea),
@@ -8448,27 +8717,33 @@ CONFIG_SOUND_WAVEFRONT
   
 Support MIDI in older MAD16 based cards (requires SB)
 CONFIG_MAD16_OLDCARD
-  Answer Y (or M) if you have an older card based on the C928
-  or Mozart chipset and you want to have  MIDI support. If you
-  enable this option you also need to enable support for Sound Blaster.
+  Answer Y (or M) if you have an older card based on the C928 or
+  Mozart chipset and you want to have MIDI support. If you enable this
+  option you also need to enable support for Sound Blaster.
 
 Support for Crystal CS4232 based (PnP) cards
 CONFIG_SOUND_CS4232
   Say Y here if you have a card based on the Crystal CS4232 chip set,
-  which uses its own Plug and Play protocol. See
-  Documentation/sound/CS4232 for more information on configuring this
-  card.
+  which uses its own Plug and Play protocol. 
+
+  See Documentation/sound/CS4232 for more information on configuring
+  this card.
+
+Support for Yamaha OPL3-SA[2,3,x] based (PnP) cards
+CONFIG_SOUND_OPL3SA2
+  Say Y or M here if you have such a sound card.
 
 Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers
 CONFIG_SOUND_MAUI
-  Say Y here if you have a Turtle Beach Wave Front, Maui, or 
-  Tropez sound card.
+  Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
+  sound card.
 
 Have OSWF.MOT firmware file
 CONFIG_MAUI_HAVE_BOOT
-  Turtle Beach Maui and Tropez sound cards have a microcontroller which
-  needs to be initialized prior to use.  OSWF.MOT is a file distributed
-  with the card's DOS/Windows drivers.  Answer Y if you have this file.
+  Turtle Beach Maui and Tropez sound cards have a microcontroller
+  which needs to be initialized prior to use. OSWF.MOT is a file
+  distributed with the card's DOS/Windows drivers. Answer Y if you
+  have this file.
 
 Full pathname of OSWF.MOT firmware file
 CONFIG_MAUI_BOOT_FILE
@@ -8477,22 +8752,23 @@ CONFIG_MAUI_BOOT_FILE
 Support for Turtle Beach MultiSound Classic, Tahiti, Monterey
 CONFIG_SOUND_MSNDCLAS
   Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
-  Monterey (not for the Pinnacle or Fiji).  See
-  Documentation/sound/MultiSound for important information about this
-  driver.
+  Monterey (not for the Pinnacle or Fiji). 
+
+  See Documentation/sound/MultiSound for important information about
+  this driver.
 
 Full pathname of MSNDINIT.BIN firmware file
 CONFIG_MSNDCLAS_INIT_FILE
   The MultiSound cards have two firmware files which are required for
-  operation, and are not currently included.  These files can be
-  obtained from Turtle Beach.  See Documentation/sound/MultiSound for
+  operation, and are not currently included. These files can be
+  obtained from Turtle Beach. See Documentation/sound/MultiSound for
   information on how to obtain this.
 
 Full pathname of MSNDPERM.BIN firmware file
 CONFIG_MSNDCLAS_PERM_FILE
   The MultiSound cards have two firmware files which are required for
-  operation, and are not currently included.  These files can be
-  obtained from Turtle Beach.  See Documentation/sound/MultiSound for
+  operation, and are not currently included. These files can be
+  obtained from Turtle Beach. See Documentation/sound/MultiSound for
   information on how to obtain this.
 
 Support for Turtle Beach MultiSound Pinnacle, Fiji
@@ -8504,61 +8780,61 @@ CONFIG_SOUND_MSNDPIN
 Full pathname of PNDSPINI.BIN firmware file
 CONFIG_MSNDPIN_INIT_FILE
   The MultiSound cards have two firmware files which are required for
-  operation, and are not currently included.  These files can be
-  obtained from Turtle Beach.  See Documentation/sound/MultiSound for
+  operation, and are not currently included. These files can be
+  obtained from Turtle Beach. See Documentation/sound/MultiSound for
   information on how to obtain this.
 
 Full pathname of PNDSPERM.BIN firmware file
 CONFIG_MSNDPIN_PERM_FILE
   The MultiSound cards have two firmware files which are required for
-  operation, and are not currently included.  These files can be
-  obtained from Turtle Beach.  See Documentation/sound/MultiSound for
+  operation, and are not currently included. These files can be
+  obtained from Turtle Beach. See Documentation/sound/MultiSound for
   information on how to obtain this.
 
 MSND Pinnacle have S/PDIF I/O
 CONFIG_MSNDPIN_DIGITAL
-  If you have the S/PDIF daughterboard for the Pinnacle or Fiji, say Y
-  here; otherwise, say N.  If you have this, you will be able to play
-  and record from the S/PDIF port (digital signal). See
+  If you have the S/PDIF daughter board for the Pinnacle or Fiji,
+  answer Y here; otherwise, say N. If you have this, you will be able
+  to play and record from the S/PDIF port (digital signal). See
   Documentation/sound/MultiSound for information on how to make use of
   this capability.
 
 MSND Pinnacle non-PnP Mode
 CONFIG_MSNDPIN_NONPNP
   The Pinnacle and Fiji card resources can be configured either with
-  PnP, or through a configuration port.  For the Pinnacle,
-  configuration in non-PnP mode allows use of the IDE and joystick
-  peripherals on the card as well, since they do not show up when the
-  card is in PnP mode.  Specifying zero for any resource of a device
-  will disable the device.  If you are running the card in PnP mode,
-  you must say N here and use isapnptools to configure the card's
-  resources.
+  PnP, or through a configuration port. Say Y here if your card is NOT
+  in PnP mode. For the Pinnacle, configuration in non-PnP mode allows
+  use of the IDE and joystick peripherals on the card as well; these
+  do not show up when the card is in PnP mode. Specifying zero for any
+  resource of a device will disable the device. If you are running the
+  card in PnP mode, you must say N here and use isapnptools to
+  configure the card's resources.
 
 MSND Pinnacle config port
 CONFIG_MSNDPIN_CFG
-  This is the port which the Pinnacle and Fiji uses to configure
-  the card's resources when not in PnP mode.  If your card is in
-  PnP mode, then be sure to say N to the previous option,
-  CONFIG_MSNDPIN_NONPNP.
+  This is the port which the Pinnacle and Fiji uses to configure the
+  card's resources when not in PnP mode. If your card is in PnP mode,
+  then be sure to say N to the previous option, "MSND Pinnacle Non-PnP
+  Mode".
 
 MSND buffer size (kB)
 CONFIG_MSND_FIFOSIZE
   Configures the size of each audio buffer, in kilobytes, for
   recording and playing in the MultiSound drivers (both the Classic
-  and Pinnacle).  Larger values reduce the chance of data overruns at
+  and Pinnacle). Larger values reduce the chance of data overruns at
   the expense of overall latency. If unsure, use the default.
 
 /dev/dsp and /dev/audio support
 CONFIG_SOUND_AUDIO
-  Answering N disables /dev/dsp and /dev/audio, the A/D and D/A
-  converter devices.  Answer N only if you know you will not need
-  the option.  They are usually required.  Answer Y.
+  If you say Y here, you will get the /dev/dsp and /dev/audio devices;
+  these are the analog-digital and digital-analog converter devices
+  and are very useful, so say Y.
 
 MIDI interface support
 CONFIG_SOUND_MIDI
   Answering N disables /dev/midixx devices and access to any MIDI
   ports using /dev/sequencer and /dev/music. This option also affects
-  any MPU401 and/or General MIDI compatible devices.  Answer Y.
+  any MPU401 and/or General MIDI compatible devices. Answer Y.
 
 FM synthesizer (YM3812/OPL-3) support
 CONFIG_SOUND_YM3812
@@ -8578,14 +8854,14 @@ CONFIG_LOWLEVEL_SOUND
 
 ACI mixer (miroPCM12)
 CONFIG_ACI_MIXER
-  Audio Command Interface (ACI) driver.  ACI is a protocol used to
-  communicate with the microcontroller on some sound cards produced
-  by miro, e.g. the miroSOUND PCM12 and PCM20.  The main function
-  of the ACI is to control the mixer and to get a product
-  identification.  This Voxware ACI driver currently only supports
-  the ACI functions on the miroSOUND PCM12 card.  On the PCM20, ACI
-  also controls the radio tuner on this card, however this is not
-  yet supported in this software.
+  Audio Command Interface (ACI) driver. ACI is a protocol used to
+  communicate with the microcontroller on some sound cards produced by
+  miro, e.g. the miroSOUND PCM12 and PCM20. The main function of the
+  ACI is to control the mixer and to get a product identification.
+  This Voxware ACI driver currently only supports the ACI functions on
+  the miroSOUND PCM12 card. On the PCM20, ACI also controls the radio
+  tuner on this card, however this is not yet supported in this
+  software.
 
 SB32/AWE support
 CONFIG_AWE32_SYNTH
@@ -8623,7 +8899,7 @@ CONFIG_SC6600
 Audio Excel DSP 16 (MSS emulation)
 CONFIG_AEDSP16_MSS
   Answer Y if you want your audio card to emulate Microsoft Sound
-  System.  You should then say Y to "Microsoft Sound System support"
+  System. You should then say Y to "Microsoft Sound System support"
   and say N to "Audio Excel DSP 16 (SBPro emulation)".
 
 Audio Excel DSP 16 (SBPro emulation)
@@ -8644,6 +8920,10 @@ CONFIG_SOUND_ES1370
   This driver differs slightly from OSS/Free, so PLEASE READ
   Documentation/sound/es1370.
 
+Joystick support at boot time
+CONFIG_SOUND_ES1370_JOYPORT_BOOT
+  Say Y here to use the joystick port of your sound card.
+
 Ensoniq ES1371 based PCI sound cards
 CONFIG_SOUND_ES1371
   Say Y or M if you have a PCI sound card utilizing the Ensoniq
@@ -8663,6 +8943,25 @@ CONFIG_SOUND_SONICVIBES
   differs slightly from OSS/Free, so PLEASE READ
   Documentation/sound/sonicvibes.
 
+Are you using a crosscompiler
+CONFIG_CROSSCOMPILE
+  Say Y here if you are compiling the kernel on a different
+  architecture than the one it is intended to run on.
+
+Build fp exception handler module
+CONFIG_MIPS_FPE_MODULE
+  Build the floating point exception handler module. This option is
+  only useful for people working on the floating point exception
+  handler. If you don't, say N.
+
+Remote GDB kernel debugging
+CONFIG_REMOTE_DEBUG
+  If you say Y here, it will be possible to remotely debug the MIPS
+  kernel using gdb. This enlarges your kernel image disk size by
+  several megabytes and requires a machine with more than 16 MB,
+  better 32 MB RAM to avoid excessive linking time. This is only
+  useful for kernel hackers. If unsure, say N.
+
 Magic System Request Key support
 CONFIG_MAGIC_SYSRQ
   If you say Y here, you will have some control over the system even
@@ -8682,10 +8981,10 @@ CONFIG_ISDN
   modem/telephone connections, and that you can have voice
   conversations while downloading stuff. It only works if your
   computer is equipped with an ISDN card and both you and your service
-  provider purchased an ISDN line from the phone company.  For
-  details, read http://alumni.caltech.edu/~dank/isdn/ on the WWW. (To
-  browse the WWW, you need to have access to a machine on the Internet
-  that has a program like lynx or netscape.)  
+  provider purchased an ISDN line from the phone company. For details,
+  read http://alumni.caltech.edu/~dank/isdn/ on the WWW. (To browse
+  the WWW, you need to have access to a machine on the Internet that
+  has a program like lynx or netscape.)
 
   This driver allows you to use an ISDN-card for networking
   connections and as dialin/out device. The isdn-tty's have a built in
@@ -8748,7 +9047,7 @@ CONFIG_ISDN_DRV_ICN
   line with two B-channels, 4B supports two ISDN lines. For running
   this card, additional firmware is necessary, which has to be
   downloaded into the card using a utility which is distributed
-  separately.  See Documentation/isdn/README and README.icn for more
+  separately. See Documentation/isdn/README and README.icn for more
   information. 
 
   If you want to compile this as a module ( = code which can be
@@ -8785,104 +9084,116 @@ CONFIG_ISDN_DRV_HISAX
 
 HiSax Support for Teles 16.0/8.0
 CONFIG_HISAX_16_0
-  This enables HiSax support for the Teles ISDN-cards S0-16.0,
-  S0-8 and many compatibles.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port/shmem settings.
+  This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
+  and many compatibles. 
+
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port/shmem settings.
 
 HiSax Support for Teles 16.3 or PNP or PCMCIA
 CONFIG_HISAX_16_3
-  This enables HiSax support for the Teles ISDN-cards S0-16.3
-  the Teles/Creatix PnP and the Teles PCMCIA.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+  This enables HiSax support for the Teles ISDN-cards S0-16.3 the
+  Teles/Creatix PnP and the Teles PCMCIA.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for Teles 16.3c
 CONFIG_HISAX_TELES3C
   This enables HiSax support for the Teles ISDN-cards 16.3c.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for AVM A1 (Fritz)
 CONFIG_HISAX_AVM_A1
   This enables HiSax support for the AVM A1 (aka "Fritz").
-  See Documentation/isdn/README.HiSax on how to configure it
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for Elsa ISA cards
 CONFIG_HISAX_ELSA
-  This enables HiSax support for the Elsa Mircolink ISA cards,
-  for the Elsa Quickstep series cards and Elsa PCMCIA.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+  This enables HiSax support for the Elsa Mircolink ISA cards, for the
+  Elsa Quickstep series cards and Elsa PCMCIA.
+
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for ITK ix1-micro Revision 2
 CONFIG_HISAX_IX1MICROR2
   This enables HiSax support for the ITK ix1-micro Revision 2 card.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for Eicon.Diehl Diva cards
 CONFIG_HISAX_DIEHLDIVA
-  This enables HiSax support for the Eicon.Diehl Diva none PRO versions
-  passive ISDN cards.
+  This enables HiSax support for the Eicon.Diehl Diva none PRO
+  versions passive ISDN cards.
 
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for ASUSCOM cards
 CONFIG_HISAX_ASUSCOM
   This enables HiSax support for the AsusCom and their OEM versions
   passive ISDN cards.
 
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for TELEINT cards
 CONFIG_HISAX_TELEINT
   This enables HiSax support for the TELEINT SA1 semiactiv ISDN card.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for Sedlbauer speed card/win-star
 CONFIG_HISAX_SEDLBAUER
   This enables HiSax support for the Sedlbauer passive ISDN cards.
-  See Documentation/isdn/README.HiSax on how to configure it 
-  using the different cards, a different D-channel protocol, or
-  non-standard IRQ/port settings.
+
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
 
 HiSax Support for USR Sportster internal TA
 CONFIG_HISAX_SPORTSTER
   This enables HiSax support for the USR Sportster internal TA card.
+
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
 HiSax Support for MIC card
 CONFIG_HISAX_MIC
-  This enables HiSax support for the ITH MIC card. See
-  Documentation/isdn/README.HiSax on how to configure it using a
+  This enables HiSax support for the ITH MIC card. 
+
+  See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
 HiSax Support for NETjet card
 CONFIG_HISAX_NETJET
   This enables HiSax support for the NetJet from Traverse
-  Technologies. See Documentation/isdn/README.HiSax on how to
-  configure it using a different D-channel protocol, or non-standard
-  IRQ/port settings.
+  Technologies.
+
+  See Documentation/isdn/README.HiSax on how to configure it using a
+  different D-channel protocol, or non-standard IRQ/port settings.
 
 HiSax Support for Niccy PnP/PCI card
 CONFIG_HISAX_NICCY
-  This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI. See
-  Documentation/isdn/README.HiSax on how to configure it using a
+  This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI. 
+
+  See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
 HiSax Support for Am7930 (EXPERIMENTAL)
@@ -8903,10 +9214,10 @@ Support for German tariff info
 CONFIG_DE_AOC
   If you want that the HiSax hardware driver sends messages to the
   upper level of the isdn code on each AOCD (Advice Of Charge, During
-  the call -- transmission of the fee information during a call) and on
-  each AOCE (Advice Of Charge, at the End of the call -- transmission
-  of fee information at the end of the call), say Y here. This works
-  only in Germany.
+  the call -- transmission of the fee information during a call) and
+  on each AOCE (Advice Of Charge, at the End of the call --
+  transmission of fee information at the end of the call), say Y here.
+  This works only in Germany.
 
 Support for Australian Microlink service (not for std. EURO)
 CONFIG_HISAX_ML
@@ -8935,7 +9246,7 @@ CONFIG_ISDN_DRV_PCBIT
   This enables support for the PCBIT ISDN-card. This card is
   manufactured in Portugal by Octal. For running this card, additional
   firmware is necessary, which has to be downloaded into the card
-  using a utility which is distributed separately.  See
+  using a utility which is distributed separately. See
   Documentation/isdn/README and Documentation/isdn/README.pcbit for
   more information. 
 
@@ -8950,7 +9261,7 @@ CONFIG_ISDN_DRV_SC
   driver currently builds only in a modularized version ( = code which
   can be inserted in and removed from the running kernel whenever you
   want, details in Documentation/modules.txt); the module will be
-  called sc.o.  See Documentation/isdn/README.sc and
+  called sc.o. See Documentation/isdn/README.sc and
   http://www.spellcast.com for more information (to browse the WWW,
   you need to have access to a machine on the Internet that has a
   program like lynx or netscape).
@@ -8965,7 +9276,7 @@ CONFIG_ISDN_DRV_AVMB1
   interface for this card is provided. In order to use this card,
   additional firmware is necessary, which has to be downloaded into
   the card using a utility which is distributed separately. Please
-  read the file Documentation/isdn/README.avmb1.  
+  read the file Documentation/isdn/README.avmb1. 
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -8975,7 +9286,7 @@ CONFIG_ISDN_DRV_AVMB1
 Verbose reason code reporting (kernel size +=7K)
 CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
   If you say Y here, the AVM B1 driver will give verbose reasons for
-  disconnecting. This will increase the size of the kernel by 7K. If
+  disconnecting. This will increase the size of the kernel by 7 KB. If
   unsure, say Y.
 
 IBM Active 2000 support (EXPERIMENTAL)
@@ -9030,21 +9341,21 @@ CONFIG_SUN_OPENPROMIO
 #
 Amiga support
 CONFIG_AMIGA
-  This option enables support for the Amiga series of computers.  If
+  This option enables support for the Amiga series of computers. If
   you plan to use this kernel on an Amiga, say Y here and browse the
   material available in Documentation/m68k; otherwise say N.
 
 Atari support
 CONFIG_ATARI
   This option enables support for the 68000-based Atari series of
-  computers (including the TT, Falcon and Medusa).  If you plan to use
+  computers (including the TT, Falcon and Medusa). If you plan to use
   this kernel on an Atari, say Y here and browse the material
   available in Documentation/m68k; otherwise say N.
 
 Hades support
 CONFIG_HADES
-  This option enables support for the Hades Atari clone. If you plan to
-  use this kernel on a Hades, say Y here; otherwise say N.
+  This option enables support for the Hades Atari clone. If you plan
+  to use this kernel on a Hades, say Y here; otherwise say N.
 
 Macintosh support
 CONFIG_MAC
@@ -9060,49 +9371,49 @@ CONFIG_MAC
 68020 support
 CONFIG_M68020
   If you anticipate running this kernel on a computer with a MC68020
-  processor, say Y.  Otherwise, say N.  Note that the 68020 requires a
-  68851 MMU (= memory management unit) to run Linux/m68k.
+  processor, say Y. Otherwise, say N. Note that the 68020 requires a
+  68851 MMU (Memory Management Unit) to run Linux/m68k.
 
 68030 support
 CONFIG_M68030
   If you anticipate running this kernel on a computer with a MC68030
-  processor, say Y.  Otherwise, say N.  Note that a MC68EC030 will not
-  work, as it does not include an MMU (= memory management unit).
+  processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
+  work, as it does not include an MMU (Memory Management Unit).
 
 68040 support
 CONFIG_M68040
   If you anticipate running this kernel on a computer with a MC68LC040
-  or MC68040 processor, say Y.  Otherwise, say N.  Note that an
-  MC68EC040 will not work, as it does not include an MMU (= memory
-  management unit).
+  or MC68040 processor, say Y. Otherwise, say N. Note that an
+  MC68EC040 will not work, as it does not include an MMU (Memory
+  Management Unit).
 
 Use -m68040 flag for 68040 specific optimizations
 CONFIG_OPTIMIZE_040
   If you will only be running this kernel on a 68040-series processor,
-  this will make the kernel run somewhat faster.  However, it will no
+  this will make the kernel run somewhat faster. However, it will no
   longer run on a 68020 or 68030, no matter whether you included 68020
-  and 68030 support or not.  Say N unless the only processor you are
+  and 68030 support or not. Say N unless the only processor you are
   compiling support for is the 68040 (or 68LC040).
 
 68060 support
 CONFIG_M68060
   If you anticipate running this kernel on a computer with a MC68060
-  processor, say Y.  Otherwise, say N.
+  processor, say Y. Otherwise, say N.
 
 Use -m68060 flag for 68060 specific optimizations
 CONFIG_OPTIMIZE_060
   If you will only be running this kernel on a 68060-series processor,
-  this will make the kernel run somewhat faster.  However, it will no
+  this will make the kernel run somewhat faster. However, it will no
   longer run on a 68020, 68030 or 68040, no matter whether you
-  included support for those processors or not.  Say N unless the only
+  included support for those processors or not. Say N unless the only
   processor you are compiling support for is the 68060.
 
 Advanced processor options
 CONFIG_ADVANCED_CPU
-  This gives you access to some advanced options for the CPU.  The
+  This gives you access to some advanced options for the CPU. The
   defaults should be fine for most users, but these options may make
   it possible for you to improve performance somewhat if you know what
-  you are doing.  Most users should say N to this question.
+  you are doing. Most users should say N to this question.
 
 Use read-modify-write instructions
 CONFIG_RMW_INSNS
@@ -9122,7 +9433,7 @@ CONFIG_ZORRO
   This enables support for automatic identification of Amiga expansion
   cards that obey the AutoConfig(tm) specification.
   Say Y if you want your expansion cards to be identified on bootup;
-  it will enlarge your kernel by about 10KB. The identification
+  it will enlarge your kernel by about 10 KB. The identification
   information is also available through /proc/zorro (say Y to
   "/proc filesystem support"!).
 
@@ -9132,13 +9443,13 @@ CONFIG_ZORRO
 Amiga OCS chipset support
 CONFIG_AMIFB_OCS
   This enables support for the original Agnus and Denise video chips,
-  found in the Amiga 1000 and most A500's and A2000's.  If you intend
+  found in the Amiga 1000 and most A500's and A2000's. If you intend
   to run Linux on any of these systems, say Y; otherwise say N.
 
 Amiga ECS chipset support
 CONFIG_AMIFB_ECS
   This enables support for the Enhanced Chip Set, found in later
-  A500's, later A2000's, the A600, the A3000, the A3000T and CDTV.  If
+  A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
   you intend to run Linux on any of these systems, say Y; otherwise
   say N.
 
@@ -9146,31 +9457,31 @@ Amiga AGA chipset support
 CONFIG_AMIFB_AGA
   This enables support for the Advanced Graphics Architecture (also
   known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
-  and CD32.  If you intend to run Linux on any of these systems, say Y;
+  and CD32. If you intend to run Linux on any of these systems, say Y;
   otherwise say N.
 
 Amiga GSP (TMS340x0) support
 CONFIG_AMIGA_GSP
   Include support for Amiga graphics cards that use the Texas
-  Instruments TMS340x0 GSP (= graphics signal processor) chips.  Say Y
+  Instruments TMS340x0 GSP (Graphics Signal Processor) chips. Say Y
   if you want to use a DMI Resolver or Commodore A2410 (Lowell)
   graphics card on an Amiga; otherwise, say N.
 
 DMI Resolver support
 CONFIG_GSP_RESOLVER
-  Include support in the kernel for the DMI Resolver graphics card.  If
+  Include support in the kernel for the DMI Resolver graphics card. If
   you have one, say Y; otherwise, say N.
 
 A2410 support
 CONFIG_GSP_A2410
   Include support in the kernel for the Commodore/University of Lowell
-  A2410 graphics card.  If you have one, say Y; otherwise, say N.
+  A2410 graphics card. If you have one, say Y; otherwise, say N.
 
 Amiga Zorro II ramdisk support
 CONFIG_AMIGA_Z2RAM
   This enables support for using Chip RAM and Zorro II RAM as a
-  ramdisk or as a swap partition.  Say Y if you want to include this
-  driver in the kernel.  This driver is also available as a module 
+  ramdisk or as a swap partition. Say Y if you want to include this
+  driver in the kernel. This driver is also available as a module 
   ( = code which can be inserted in and removed from the running
   kernel whenever you want). The module is called z2ram.o. If you want
   to compile it as a module, say M here and read
@@ -9219,13 +9530,13 @@ CONFIG_ATARI_SLM
   it in the kernel. Otherwise, say N. This driver is also available as
   a module ( = code which can be inserted in and removed from the
   running kernel whenever you want). The module will be called
-  acsi_slm.o.  Be warned: the driver needs much ST-RAM and can cause
+  acsi_slm.o. Be warned: the driver needs much ST-RAM and can cause
   problems due to that fact!
 
 A3000 WD33C93A support
 CONFIG_A3000_SCSI
   If you have an Amiga 3000 and have SCSI devices connected to the
-  built-in SCSI controller, say Y.  Otherwise, say N.  This driver is
+  built-in SCSI controller, say Y. Otherwise, say N. This driver is
   also available as a module ( = code which can be inserted in and
   removed from the running kernel whenever you want). The module is
   called wd33c93.o. If you want to compile it as a module, say M here
@@ -9233,19 +9544,19 @@ CONFIG_A3000_SCSI
 
 A2091 WD33C93A support
 CONFIG_A2091_SCSI
-  If you have a Commodore A2091 SCSI controller, say Y.  Otherwise,
-  say N.  This driver is also available as a module ( = code which can
+  If you have a Commodore A2091 SCSI controller, say Y. Otherwise,
+  say N. This driver is also available as a module ( = code which can
   be inserted in and removed from the running kernel whenever you
   want). The module is called wd33c93.o. If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
 
 GVP Series II WD33C93A support
 CONFIG_GVP11_SCSI
-  If you have a Great Valley Products Series II SCSI controller, say
-  Y.  Also say Y if you have a later model of GVP SCSI controller
-  (such as the GVP A4008 or a Combo board).  Otherwise, say N.
-  This driver does NOT work for the T-Rex series of accelerators from
-  TekMagic and GVP-M.
+  If you have a Great Valley Products Series II SCSI controller,
+  answer Y. Also say Y if you have a later model of GVP SCSI
+  controller (such as the GVP A4008 or a Combo board). Otherwise,
+  answer N. This driver does NOT work for the T-Rex series of
+  accelerators from TekMagic and GVP-M.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you
@@ -9255,36 +9566,36 @@ CONFIG_GVP11_SCSI
 Cyberstorm SCSI support
 CONFIG_CYBERSTORM_SCSI
   If you have an Amiga with an original (MkI) Phase5 Cyberstorm
-  accelerator board and the optional Cyberstorm SCSI controller, say
-  Y.  Otherwise, say N.
+  accelerator board and the optional Cyberstorm SCSI controller,
+  answer Y. Otherwise, say N.
 
 Cyberstorm II SCSI support
 CONFIG_CYBERSTORMII_SCSI
   If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board
-  and the optional Cyberstorm SCSI controller, say Y. Otherwise, say
-  N.
+  and the optional Cyberstorm SCSI controller, say Y. Otherwise,
+  answer N.
 
 Blizzard 2060 SCSI support
 CONFIG_BLZ2060_SCSI
   If you have an Amiga with a Phase5 Blizzard 2060 accelerator board
-  and want to use the onboard SCSI controller, say Y. Otherwise, say
-  N.
+  and want to use the onboard SCSI controller, say Y. Otherwise,
+  answer N.
 
 Blizzard 1230IV/1260 SCSI support
 CONFIG_BLZ1230_SCSI
   If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard
-  1260 accelerator, and the optional SCSI module, say Y.  Otherwise,
+  1260 accelerator, and the optional SCSI module, say Y. Otherwise,
   say N.
 
 Blizzard PowerUP 603e+ SCSI support
 CONFIG_BLZ603EPLUS_SCSI
   If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+
-  accelerator, say Y.  Otherwise, say N.
+  accelerator, say Y. Otherwise, say N.
 
 Fastlane SCSI support
 CONFIG_FASTLANE_SCSI
   If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
-  one in the near future, say Y to this question.  Otherwise, say N.
+  one in the near future, say Y to this question. Otherwise, say N.
 
 Atari native SCSI support
 CONFIG_ATARI_SCSI
@@ -9294,7 +9605,7 @@ CONFIG_ATARI_SCSI
   available as a module ( = code which can be inserted in and removed
   from the running kernel whenever you want). The module is called
   atari_scsi.o. If you want to compile it as a module, say M here and
-  read Documentation/modules.txt.  This driver supports both styles of
+  read Documentation/modules.txt. This driver supports both styles of
   NCR integration into the system: the TT style (separate DMA), and
   the Falcon style (via ST-DMA, replacing ACSI). It does NOT support
   other schemes, like in the Hades (without DMA).
@@ -9316,7 +9627,7 @@ CONFIG_TT_DMA_EMUL
 
 Ariadne support
 CONFIG_ARIADNE
-  If you have a Village Tronic Ariadne Ethernet adapter, say Y.
+  If you have a VillageTronics Ariadne Ethernet adapter, say Y.
   Otherwise, say N.
 
   This driver is also available as a module ( = code which can be
@@ -9326,7 +9637,7 @@ CONFIG_ARIADNE
 
 Ariadne II support
 CONFIG_ARIADNE2
-  If you have a Village Tronic Ariadne II Ethernet adapter, say Y.
+  If you have a VillageTronics Ariadne II Ethernet adapter, say Y.
   Otherwise, say N.
 
   This driver is also available as a module ( = code which can be
@@ -9336,7 +9647,7 @@ CONFIG_ARIADNE2
 
 A2065 support
 CONFIG_A2065
-  If you have a Commodore A2065 Ethernet adapter, say Y.  Otherwise,
+  If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
   say N.
 
   This driver is also available as a module ( = code which can be
@@ -9346,7 +9657,7 @@ CONFIG_A2065
 
 Hydra support
 CONFIG_HYDRA
-  If you have a Hydra Ethernet adapter, say Y.  Otherwise, say N.
+  If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you
@@ -9374,7 +9685,7 @@ CONFIG_ATARI_PAMSNET
 Multiface Card III parallel support
 CONFIG_MULTIFACE_III_LP
   If you have a Multiface III card for your Amiga, and want to use its
-  parallel port in Linux, say Y.  Otherwise, say N.  
+  parallel port in Linux, say Y. Otherwise, say N.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -9383,7 +9694,7 @@ CONFIG_MULTIFACE_III_LP
 
 Amiga mouse support
 CONFIG_AMIGAMOUSE
-  If you want to be able to use an Amiga mouse in Linux, say Y.  
+  If you want to be able to use an Amiga mouse in Linux, say Y. 
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -9393,13 +9704,13 @@ CONFIG_AMIGAMOUSE
 Amiga Copper Console
 CONFIG_COPCON
   This configures the console to use the Amiga's graphics coprocessor
-  for scrolling, instead of using the CPU.  This option markedly
+  for scrolling, instead of using the CPU. This option markedly
   improves response times in the high color modes (5 bitplanes and
-  up).  If you would like to use this, say Y; otherwise, say N.
+  up). If you would like to use this, say Y; otherwise, say N.
 
 Atari mouse support
 CONFIG_ATARIMOUSE
-  If you want to be able to use an Atari mouse in Linux, say Y.  
+  If you want to be able to use an Atari mouse in Linux, say Y. 
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -9426,7 +9737,7 @@ CONFIG_ATARI_SCC
   LAN) and like to use them under Linux, say Y. All built-in SCC's are
   supported (TT, MegaSTE, Falcon), and also the ST-ESCC. If you have
   two connectors for channel A (Serial2 and LAN), they are visible as
-  two separate devices. 
+  two separate devices.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -9435,9 +9746,9 @@ CONFIG_ATARI_SCC
 
 Atari SCC serial DMA support
 CONFIG_ATARI_SCC_DMA
-  This enables DMA support for receiving data on channel A of the
-  SCC. If you have a TT you may say Y here and read
-  drivers/char/atari_SCC.README.  All other users should say N here,
+  This enables DMA support for receiving data on channel A of the SCC.
+  If you have a TT you may say Y here and read
+  drivers/char/atari_SCC.README. All other users should say N here,
   because only the TT has SCC-DMA, even if your machine keeps claiming
   so at boot time.
 
@@ -9452,19 +9763,19 @@ CONFIG_ATARI_MIDI
 
 Atari DSP56k Digital Signal Processor support
 CONFIG_ATARI_DSP56K
-  If you want to be able to use the DSP56001 in Falcons, say Y.
-  This driver is still experimental, and if you don't know what it is,
-  or if you don't have this processor, just say N.
+  If you want to be able to use the DSP56001 in Falcons, say Y. This
+  driver is still experimental, and if you don't know what it is, or
+  if you don't have this processor, just say N.
 
-  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
+  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.
 
 Amiga builtin serial support
 CONFIG_AMIGA_BUILTIN_SERIAL
-  If you want to use your Amiga's built-in serial port in Linux, say
-  Y.
+  If you want to use your Amiga's built-in serial port in Linux,
+  answer Y.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you
@@ -9478,8 +9789,8 @@ CONFIG_GVPIOEXT
 
 Multiface Card III serial support
 CONFIG_MULTIFACE_III_TTY
-  If you want to use a Multiface III card's serial port in Linux, say
-  Y.
+  If you want to use a Multiface III card's serial port in Linux,
+  answer Y.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -9489,8 +9800,8 @@ CONFIG_MULTIFACE_III_TTY
 Amiga or Atari DMA sound support
 CONFIG_DMASOUND
   If you want to use the internal audio of your Atari or Amiga in
-  Linux, answer Y to this question.  This will provide a Sun-like
-  /dev/audio, compatible with the Linux/i386 sound system.  Otherwise,
+  Linux, answer Y to this question. This will provide a Sun-like
+  /dev/audio, compatible with the Linux/i386 sound system. Otherwise,
   say N.
 
   This driver is also available as a module ( = code which can be
@@ -9501,41 +9812,40 @@ CONFIG_DMASOUND
 MSDOS partition support
 CONFIG_MSDOS_PARTITION
   This option enables support for using hard disks that were
-  partitioned on an MS-DOS system.  This may be useful if you are
+  partitioned on an MS-DOS system. This may be useful if you are
   sharing a hard disk between i386 and m68k Linux boxes, for example.
   Say Y if you need this feature; users who are only using their
   system-native partitioning scheme can say N here.
 
 Processor Type
 CONFIG_6xx
-  There are two types of PowerPC chips supported.  The more common
+  There are two types of PowerPC chips supported. The more common
   types (601,603,604,740,750) and the embedded versions (821 and 860).
-  Unless you are building a kernel for one of the embedded boards using
-  the 821 or 860 choose 6xx.
+  Unless you are building a kernel for one of the embedded boards
+  using the 821 or 860 choose 6xx.
 
 Machine Type
 CONFIG_PMAC
   Linux currently supports several different kinds of PowerPC-based
-  machines: Apple Power Macintoshes and clones (such as the
-  Motorola Starmax series), PReP (PowerPC Reference Platform) machines
-  such as the Motorola PowerStack, Amiga Power-Up systems (APUS), CHRP
-  and the embedded MBX boards from Motorola. Currently, a single
-  kernel binary only supports one type or the other. However, there is
-  very early work on support for CHRP, PReP and PowerMac's from a
-  single binary.
+  machines: Apple Power Macintoshes and clones (such as the Motorola
+  Starmax series), PReP (PowerPC Reference Platform) machines such as
+  the Motorola PowerStack, Amiga Power-Up systems (APUS), CHRP and the
+  embedded MBX boards from Motorola. Currently, a single kernel binary
+  only supports one type or the other. However, there is very early
+  work on support for CHRP, PReP and PowerMac's from a single binary.
 
 Support for Open Firmware device tree in /proc
 CONFIG_PROC_DEVICETREE
   This option adds a device-tree directory under /proc which contains
   an image of the device tree that the kernel copies from Open
-  Firmware.  If unsure, say Y here.
+  Firmware. If unsure, say Y here.
 
 MESH (Power Mac internal SCSI) support
 CONFIG_SCSI_MESH
   Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
   SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the
-  other Power Macintoshes do).  Say Y to include support for this SCSI
-  adaptor.  This driver is also available as a module called mesh.o
+  other Power Macintoshes do). Say Y to include support for this SCSI
+  adaptor. This driver is also available as a module called mesh.o
   ( = 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.
@@ -9545,18 +9855,18 @@ CONFIG_SCSI_MESH_SYNC_RATE
   On Power Macintoshes (and clones) where the MESH SCSI bus adaptor
   drives a bus which is entirely internal to the machine (such as the
   7500, 7600, 8500, etc.), the MESH is capable of synchronous
-  operation at up to 10MB/s.  On machines where the SCSI bus
+  operation at up to 10 MB/s. On machines where the SCSI bus
   controlled by the MESH can have external devices connected, it is
-  usually rated at 5MB/s.  5 is a safe value here unless you know the
-  MESH SCSI bus is internal only; in that case you can say 10.  Say 0
+  usually rated at 5 MB/s. 5 is a safe value here unless you know the
+  MESH SCSI bus is internal only; in that case you can say 10. Say 0
   to disable synchronous operation.
 
 53C94 (Power Mac external SCSI) support
 CONFIG_SCSI_MAC53C94
   On Power Macintoshes (and clones) with two SCSI buses, the external
-  SCSI bus is usually controlled by a 53C94 SCSI bus adaptor.  Older
+  SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older
   machines which only have one SCSI bus, such as the 7200, also use
-  the 53C94.  Say Y to include support for the 53C94.  
+  the 53C94. Say Y to include support for the 53C94. 
 
   This driver is also available as a module called mac53c94.o ( = code
   which can be inserted in and removed from the running kernel
@@ -9567,7 +9877,7 @@ MACE (Power Mac Ethernet) support
 CONFIG_MACE
   Power Macintoshes and clones with Ethernet built-in on the
   motherboard will usually use a MACE (Medium Access Control for
-  Ethernet) interface.  Say Y to include support for the MACE chip.
+  Ethernet) interface. Say Y to include support for the MACE chip.
 
 BMAC (G3 ethernet) support
 CONFIG_BMAC
@@ -9600,7 +9910,7 @@ CONFIG_RADIO_RTRACK
   RadioTrack II driver below.
 
   In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API.  Information on 
+  that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
   http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
   you need to have access to a machine on the Internet that has a 
@@ -9614,7 +9924,7 @@ CONFIG_RADIO_RTRACK
 
 RadioTrack i/o port
 CONFIG_RADIO_RTRACK_PORT
-  Enter either 0x30f or 0x20f here.  The card default is 0x30f, if you
+  Enter either 0x30f or 0x20f here. The card default is 0x30f, if you
   haven't changed the jumper setting on the card.
 
 AIMSlab RadioTrack II support
@@ -9623,7 +9933,7 @@ CONFIG_RADIO_RTRACK2
   port address below.
 
   In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API.  Information on 
+  that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
   http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
   you need to have access to a machine on the Internet that has a 
@@ -9636,7 +9946,7 @@ CONFIG_RADIO_RTRACK2
 
 RadioTrack II i/o port
 CONFIG_RADIO_RTRACK2_PORT
-  Enter either 0x30c or 0x20c here.  The card default is 0x30c, if you
+  Enter either 0x30c or 0x20c here. The card default is 0x30c, if you
   haven't changed the jumper setting on the card.
 
 Aztech/Packard Bell Radio
@@ -9645,7 +9955,7 @@ CONFIG_RADIO_AZTECH
   in the port address below.
   
   In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API.  Information on 
+  that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
   http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
   you need to have access to a machine on the Internet that has a 
@@ -9658,8 +9968,8 @@ CONFIG_RADIO_AZTECH
 
 Aztech/Packard Bell radio card i/o port
 CONFIG_RADIO_AZTECH_PORT
-  Enter either 0x350 or 0x358 here.  The card default is 0x350, if you
-  haven't changed the setting of jumper JP3 on the card.  Removing the
+  Enter either 0x350 or 0x358 here. The card default is 0x350, if you
+  haven't changed the setting of jumper JP3 on the card. Removing the
   jumper sets the card to 0x358.
 
 SF16FMI Radio
@@ -9668,7 +9978,7 @@ CONFIG_RADIO_SF16FMI
   in the port address below.
 
   In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API.  Information on 
+  that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
   http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
   you need to have access to a machine on the Internet that has a 
@@ -9689,7 +9999,7 @@ CONFIG_RADIO_ZOLTRIX
   in the port address below.
 
   In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API.  Information on 
+  that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
   http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
   you need to have access to a machine on the Internet that has a 
@@ -9710,7 +10020,7 @@ CONFIG_RADIO_MIROPCM20
   in the port address below.
 
   In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API.  Information on 
+  that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
   http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
   you need to have access to a machine on the Internet that has a 
@@ -9769,17 +10079,17 @@ CONFIG_VIDEO_PMS
 
 CPU Optimization
 CONFIG_CPU_ARM2
-  This selects the processor type of your CPU.  This is only used to
+  This selects the processor type of your CPU. This is only used to
   determine C compiler optimization options, and can affect the
-  compatibility of the kernel on other processors.  If you specify
-  ARM6, the kernel should work on all 32-bit processors.  If you
+  compatibility of the kernel on other processors. If you specify
+  ARM6, the kernel should work on all 32-bit processors. If you
   specify ARM2, ARM250 or ARM3, it should work on all 26-bit
-  processors.  If you're not sure, set it to "None".
+  processors. If you're not sure, set it to "None".
 
 ARM System type
 CONFIG_ARCH_ARC
-  This selects what ARM system you wish to build the kernel for.  It
-  also selects to some extent the CPU type.  If you are unsure what
+  This selects what ARM system you wish to build the kernel for. It
+  also selects to some extent the CPU type. If you are unsure what
   to set this option to, please consult any information supplied with
   your system.
 
@@ -9795,51 +10105,6 @@ CONFIG_FRAME_POINTER
   it will give useful debugging/error results. If you don't debug the
   kernel, you can say N.
 
-VIDC Sound
-CONFIG_VIDC_SOUND
-  Say 'Y' here for ARM systems with the VIDC video controller and 16-bit
-  Linear sound DACs.  If unsure, say N.
-
-Backward compatibility mode for Xpmac
-CONFIG_FB_COMPAT_XPMAC
-  If you use the Xpmac X server (common with mklinux), you'll need
-  to enable this to use X. You should consider changing to XFree86
-  which includes a server that supports the frame buffer device
-  directly (XF68_FBDev).
-
-Support for PowerMac keyboard
-CONFIG_MAC_KEYBOARD
-  This option allows you to use an ADB keyboard attached to your
-  machine. Note that this disables any other (ie. PS/2) keyboard
-  support, even if your machine is physically capable of using both
-  at the same time.
-  
-  If you use an ADB keyboard (4 pin connector), say Y here.
-  If you use a PS/2 keyboard (6 pin connector), say N here.
-
-Support for PowerMac floppy
-CONFIG_MAC_FLOPPY
-  If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
-  floppy controller, say Y here. Most commonly found in PowerMacs.
-
-Support for PowerMac serial ports
-CONFIG_MAC_SERIAL
-  If you have Macintosh style serial ports (8 pin mini-DIN), this
-  is the driver for them. If you also have regular serial ports
-  and enable the driver for them, you can't currently use the
-  serial console feature.
-
-Support for PowerMac ADB mouse
-CONFIG_ADBMOUSE
-  If you have an ADB mouse (4 pin connector) as is common on
-  Macintoshes, say Y here.
-
-Winbond SL82c105 support
-CONFIG_BLK_DEV_SL82C105
-  If you have a Winbond SL82c105 IDE controller, say Y here to
-  enable special configuration for this chip. This is common
-  on various CHRP motherboards, but could be used elsewhere.
-  If in doubt, say Y.
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DMA, FTP, Internet, Intel, IRQ, 
@@ -9891,13 +10156,13 @@ CONFIG_BLK_DEV_SL82C105
 # 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 SmartRAID SmartCache httpd sjc dlp
-# LocalWords:  thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ chipsets MG
+# LocalWords:  thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ MG HIPPI cern
 # LocalWords:  bsd comp SPARCstation le SunOS ie Gracilis PackeTwin PT pt LU FX
 # LocalWords:  FX TEAC CR LCS mS ramdisk IDETAPE cmd fperllo encis tcfs unisa
 # LocalWords:  Vertos Genoa Funai hsfs NCP NetWare tgz APM apm ioctls UltraLite
 # LocalWords:  TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrecord pg
 # LocalWords:  PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT
-# LocalWords:  KERNELD kerneld callouts AdvanSys advansys Admin WDT DataStor EP
+# LocalWords:  kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden
 # LocalWords:  wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI
 # LocalWords:  QD qd UMC umc ALI ali lena fnet fr azstarnet axplinux cdr fb MDA
 # LocalWords:  Avanti XL AlphaStations Jensen DECpc AXPpci UDB Cabriolet MCA RC
@@ -9948,7 +10213,7 @@ CONFIG_BLK_DEV_SL82C105
 # LocalWords:  INSNS Ataris AutoConfig ZORRO OCS AMIFB Agnus Denise ECS CDTV GB
 # LocalWords:  AGA Cybervision CYBER GSP TMS DMI Zorro ACSI ROMs SLM BioNet GVP
 # LocalWords:  PAMsNet TekMagic Cyberstorm MkI CYBERSTORMII MkII BLZ onboard cx
-# LocalWords:  Village Tronic ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB
+# LocalWords:  VillageTronics ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB
 # LocalWords:  Rhotron BioData's Multiface AMIGAMOUSE COPCON Amiga's bitplanes
 # LocalWords:  ATARIMOUSE MFPSER SCC's MegaSTE ESCC Atari's GVPIOEXT DMASOUND
 # LocalWords:  fdutils cisco univercd rpcg htm iface lapb LAPBETHER tpqic qic
@@ -9971,7 +10236,7 @@ CONFIG_BLK_DEV_SL82C105
 # LocalWords:  zorro CAPI AVMB capi avmb VP SYN syncookies EM em pc Ethertalk
 # LocalWords:  Dayna DL Daynatalk LT PhoneNET ATB Daystar queueing CMDS SCBs ls
 # LocalWords:  SCB STATS Thinnet ThunderLAN TLAN Netelligent NetFlex tlan james
-# LocalWords:  caldera Preload dcache Preloading slowdowns schoebel uni NBD nbd
+# LocalWords:  caldera Preload Preloading slowdowns schoebel uni NBD nbd prog
 # LocalWords:  stuttgart rdist TRANS hostnames mango jukeboxes ESS userland PD
 # LocalWords:  hardlinked NAMETRANS env mtab fstab umount nologin runlevel gid
 # LocalWords:  transname filespace adm Nodename hostname uname Kernelname bootp
@@ -10033,6 +10298,19 @@ CONFIG_BLK_DEV_SL82C105
 # LocalWords:  CyberVision Cirrus PowerBooks Topcat SBUS CGsix TurboGX BWtwo SS
 # LocalWords:  CGthree TCX unswapable vfb fbcon hicolor truecolor AFB ILBM SOC
 # LocalWords:  IPLAN gracilis Fibre SBus SparcSTORAGE SV jnewbigin swin QNX qnx
-# LocalWords:  PTY PTYS ptyxx ttyxx PTYs ssh sb Avance ALS pss
-# LocalWords:  synth WaveFront MSND NONPNP AudioExcelDSP STRAM APUS CHRP MBX
-# LocalWords:  PowerMac's BMAC radiotrack rtrack miropcm
+# LocalWords:  PTY PTYS ptyxx ttyxx PTYs ssh sb Avance ALS pss pvv kerneli hd
+# LocalWords:  synth WaveFront MSND NONPNP AudioExcelDSP STRAM APUS CHRP MBX Nx
+# LocalWords:  PowerMac's BMAC radiotrack rtrack miropcm OFFBOARD HPT UDMA DVD
+# LocalWords:  hpt fokus gmd Cyrix DXL SLC DLC NexGen MediaGX GXm IDT WinChip
+# LocalWords:  MMX MII valkyrie mdacon vdolive VDOLive cuseeme CU hippi rrunner
+# LocalWords:  SeeMe ipmasqadm juanjox ipmarkfw markfw TNCs Microdyne rhine lib
+# LocalWords:  libc jsX gamepad gameport CHF FCS FPGaming MadCatz ASSASIN GrIP
+# LocalWords:  Assasin gamepads GamePad PDPI gamecards gamecard WingMan BSP WCS
+# LocalWords:  ThunderPad CyberMan SideWinder ThrustMaster DirectConnect NES XF
+# LocalWords:  Millenium SNES PSX Multisystem Nintendo PlayStation Amstrad CPC
+# LocalWords:  Sega TurboGraFX Steffen Schwenke Multiststem PDIF FIFOSIZE EPLUS
+# LocalWords:  PowerUP RoadRunner tahallah dos functionkey setterm imladris Woz
+# LocalWords:  PowerMacs Winbond Algorithmics ALGOR algor ECOFF IRIX SGI SGI's
+# LocalWords:  gfx virtualized Xpmac mklinux XFree FBDev Woodhouse mvhi Seeq fp
+# LocalWords:  SGISEEQ HIgh ADB ADBMOUSE crosscompiler CROSSCOMPILE FPE GDB gdb
+# LocalWords:  JOYPORT rp spoofing DawiControl NOGENSUPP EEPROM HSSI
index cd0222464bac1fbd59ba4274efe73c77024ce373..9de8045328d812ef9bc73bb3126e8cd459c8842e 100644 (file)
@@ -279,8 +279,8 @@ Slot 5: db 8f 1d 5e fd c0 00 00
 Slot 6: ff ff ff ff ff ff ff ff  
 Slot 7: 42 60 ff 08 ff ff ff ff  3Com 3c523 Etherlink/MC
 Slot 8: ff ff ff ff ff ff ff ff  
-Video: ff ff ff ff ff ff ff ff  
-SCSI: ff ff ff ff ff ff ff ff  
+Video : ff ff ff ff ff ff ff ff  
+SCSI  : ff ff ff ff ff ff ff ff  
 
 /proc/mca/slot1:
 Slot: 1
index 5525e236a08acd87a1ac758a2132c56d857f1848..d29c4c66f03cdfe84424b67a7dced3ed866ee6bb 100644 (file)
@@ -15,6 +15,7 @@ system, it is advisable to read both documentation and source
 before actually making adjustments.
 
 Currently, these files are in /proc/sys/kernel:
+- acct
 - ctrl-alt-del
 - dentry-state
 - domainname
@@ -36,6 +37,23 @@ Currently, these files are in /proc/sys/kernel:
 
 ==============================================================
 
+acct:
+
+highwater lowwater frequency
+
+If BSD-style process accounting is enabled these values control
+its behaviour. If free space on filesystem where the log lives
+goes below <lowwater>% accounting suspends. If free space gets
+above <highwater>% accounting resumes. <Frequency> determines
+how often do we check the amount of free space (value is in
+seconds). Default:
+4 2 30
+That is, suspend accounting if there left <= 2% free; resume it
+if we got >=4%; consider information about amount of free space
+valid for 30 seconds.
+
+==============================================================
+
 ctrl-alt-del:
 
 When the value in this file is 0, ctrl-alt-del is trapped and
index 52cac1e6cf613646863c494b9fb7f6b952c29689..9b5de6cb6545837888e71d55caa85cb9a41f7826 100644 (file)
@@ -20,6 +20,7 @@
     5: Philips PAL tuner
     6: Temic NTSC tuner
     7: Temic PAL tuner
+    8: Temic 4036 FY5 NTSC tuner
 
     The number corresponds to the number (-1) given at the GPIO port of the
     Bt848 on Miro cards.
     4: Intel
     5: Diamond
     6: AVerMedia
-
+    7: Matrix Vision MV-Delta
+    8: Fly Video II
+    9: TurboTV
+   10: Newer Hauppage (Bt878)
+   11: Miro PCTV Pro
+   12: ADS Tech Channel Surfer TV (and maybe TV+FM)
 
   - You may have to adjust BTTV_MAJOR to a different number depending on your
     kernel version. The official number 81 does not work on some setups.
index 370d9e163beaf407372be00cf168e190d548e66c..9a2a813ef4c628ab52dda6a69fc86bbb91aa2563 100644 (file)
@@ -204,7 +204,7 @@ M:  hpa@zytor.com
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
-DIGI INTL. EPCA DRIVER:
+DIGI INTL. EPCA DRIVER
 P:      Daniel Taylor
 M:      support@dgii.com
 M:      digilnux@dgii.com
@@ -277,7 +277,7 @@ M:  mike.mclagan@linux.org
 L:     linux-net@vger.rutgers.edu
 S:     Maintained
 
-FTAPE/QIC-117:
+FTAPE/QIC-117
 P:     Claus-Justus Heine
 M:     claus@momo.math.rwth-aachen.de
 L:     linux-tape@vger.rutgers.edu
@@ -297,7 +297,7 @@ L:  linux-scsi@vger.rutgers.edu
 W:     http://www.icp-vortex.com/
 S:     Supported
 
-HAYES ESP SERIAL DRIVER:
+HAYES ESP SERIAL DRIVER
 P:     Andrew J. Robinson
 M:     arobinso@nyx.net
 L:     linux-kernel@vger.rutgers.edu
@@ -396,14 +396,14 @@ M:        paulus@cs.anu.edu.au
 L:     linux-pmac@samba.anu.edu.au
 S:     Maintained
 
-M68K:
+M68K
 P:     Jes Sorensen
 M:     Jes.Sorensen@cern.ch
 W:     http://www.clark.net/pub/lawrencc/linux/index.html
 L:     linux-m68k@lists.linux-m68k.org
 S:     Maintained
 
-M68K ON APPLE MACINTOSH:
+M68K ON APPLE MACINTOSH
 P:     Alan Cox
 M:     Alan.Cox@linux.org
 W:     http://www.mac.linux-m68k.org/home.html
@@ -416,19 +416,26 @@ M:        philb@gnu.org
 W:     http://www.tazenda.demon.co.uk/phil/linux-hp
 S:     Maintained
 
-MENUCONFIG:
+MENUCONFIG
 P:     Michael Elizabeth Chastain
 M:     mec@shout.net
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
-MIPS:
+MIPS
 P:     Ralf Baechle
 M:     ralf@gnu.ai.mit.edu
 W:     http://lena.fnet.fr/
 L:     linux-mips@fnet.fr
 S:     Maintained
 
+MISCELLANEOUS MCA-SUPPORT
+P:     David Weinehall
+M:     mcalinux@acc.umu.se (project MCA-team)
+M:     tao@acc.umu.se (personal)
+L:     linux-kernel@vger.rutgers.edu
+S:     Maintained
+
 MODULE SUPPORT [GENERAL], KERNELD
 P:     Richard Henderson
 M:     richard@gnu.ai.mit.edu
@@ -446,7 +453,7 @@ P:  Andrew Veliath
 M:     andrewtv@usa.net
 S:     Maintained
 
-NCP FILESYSTEM:
+NCP FILESYSTEM
 P:     Petr Vandrovec
 M:     vandrove@vc.cvut.cz
 P:     Volker Lendecke
@@ -465,14 +472,14 @@ P:        Pavel Machek
 M:     pavel@atrey.karlin.mff.cuni.cz
 S:     Maintained
 
-NETWORKING [GENERAL]:
+NETWORKING [GENERAL]
 P:     Networking Teak
 M:     netdev@nuclecu.unam.mx
 L:     linux-net@vger.rutgers.edu
 W:     http://www.uk.linux.org/NetNews.html (2.0 only)
 S:     Maintained
 
-NETWORKING [IPv4/IPv6]:
+NETWORKING [IPv4/IPv6]
 P:     David S. Miller
 M:     davem@caip.rutgers.edu
 P:     Eric Schenk
@@ -565,7 +572,7 @@ M:  frible@teaser.fr
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
 
-RISCOM8 DRIVER:
+RISCOM8 DRIVER
 P:     Dmitry Gorodchanin
 M:     pgmdsg@ibi.com
 L:     linux-kernel@vger.rutgers.edu
@@ -587,7 +594,7 @@ M:  Kai.Makisara@metla.fi
 L:     linux-scsi@vger.rutgers.edu
 S:     Maintained
 
-SMB FILESYSTEM:
+SMB FILESYSTEM
 P:     Volker Lendecke
 M:     lendecke@Math.Uni-Goettingen.de
 L:     samba@listproc.anu.edu.au
@@ -642,7 +649,7 @@ M:  cheshire@cs.stanford.edu
 W:     http://mosquitonet.Stanford.EDU/strip.html
 S:     Maintained
 
-SVGA HANDLING:
+SVGA HANDLING
 P:     Martin Mares
 M:     mj@atrey.karlin.mff.cuni.cz
 L:     linux-video@atrey.karlin.mff.cuni.cz
@@ -661,7 +668,7 @@ S:  Maintained
 
 TOKEN-RING NETWORK DRIVER
 P:     Paul Norton
-M:     p.norton@computer.org
+M:     pnorton@ieee.org
 L:     linux-net@vger.rutgers.edu
 L:     linux-tr@emissary.aus-etc.com
 S:     Maintained
@@ -737,6 +744,6 @@ W:  http://qsl.net/dl1bke/
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
 
-REST:
+THE REST
 P:     Linus Torvalds
 S:     Buried alive in diapers
index a357515468ecdb8774c9ed0198ecdb68d9ecefd0..a2e14844698527b71939540e8e72e0b7b2f7c7f8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 127
+SUBLEVEL = 128
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index eba6929dc4644ab439c0c5866cb0d12e653d85a8..00c1226cd88114d4c5e652c110fcb314cbfaa21b 100644 (file)
@@ -589,7 +589,7 @@ __initfunc(void time_init(void))
  * still perfectly ordered.
  * Note that the TSC counter will be reset if APM suspends
  * to disk; this won't break the kernel, though, 'cuz we're
- * smart.  See devices/char/apm_bios.c.
+ * smart.  See arch/i386/kernel/apm.c.
  */
        if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
                do_gettimeoffset = do_fast_gettimeoffset;
index 01bd41ce4dedd8fe34cfc74f33f18d4d2fcf67bb..6e9a954230087c3dcc3450634884ae3ceaac8eae 100644 (file)
 #include <linux/init.h>
 #include <linux/delay.h>
 
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#include <asm/processor.h>
+#endif
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -295,6 +300,14 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs)
 
 static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 {
+#ifdef CONFIG_MCA
+       /* Might actually be able to figure out what the guilty party
+       * is. */
+       if( MCA_bus ) {
+               mca_handle_nmi();
+               return;
+       }
+#endif
        printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
        printk("Dazed and confused, but trying to continue\n");
        printk("Do you have a strange power saving mode enabled?\n");
index 09a34ecf48153f1fdec0fcaa2ff6ec6503af430e..cade2173ab1251fd8f8dd26677745dd9d6ba1db2 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
+#include <linux/shm.h>
+
 #include <asm/setup.h>
 #include <asm/machdep.h>
 #include <asm/page.h>
@@ -26,6 +28,7 @@
 #include <asm/atarihw.h>
 #include <asm/atari_stram.h>
 #include <asm/io.h>
+#include <asm/semaphore.h>
 
 
 #ifdef CONFIG_STRAM_SWAP
  * since the freeing algorithms are also blind to DMA capability of pages.
  */
 
+/* 1998-10-20: ++andreas
+   unswap_by_move disabled because it does not handle swapped shm pages.
+*/
+
 #ifdef CONFIG_STRAM_SWAP
 #define ALIGN_IF_SWAP(x)       PAGE_ALIGN(x)
 #else
@@ -192,6 +199,9 @@ static struct swap_info_struct *stram_swap_info;
 /* The ST-RAM's swap type */
 static int stram_swap_type;
 
+/* Semaphore for get_stram_region.  */
+static struct semaphore stram_swap_sem = MUTEX;
+
 /* major and minor device number of the ST-RAM device; for the major, we use
  * the same as Amiga z2ram, which is really similar and impossible on Atari,
  * and for the minor a relatively odd number to avoid the user creating and
@@ -215,25 +225,6 @@ static unsigned stat_swap_force = 0;
 
 #ifdef CONFIG_STRAM_SWAP
 static int swap_init( unsigned long start_mem, unsigned long swap_data );
-static inline int unswap_pte( struct vm_area_struct * vma, unsigned long
-                             address, pte_t *dir, unsigned long entry,
-                             unsigned long page, int isswap );
-static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir,
-                             unsigned long address, unsigned long size,
-                             unsigned long offset, unsigned long entry,
-                             unsigned long page, int isswap );
-static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir,
-                             unsigned long address, unsigned long size,
-                             unsigned long entry, unsigned long page, int
-                             isswap );
-static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, unsigned
-                      long entry, unsigned long page, int isswap );
-static int unswap_process( struct mm_struct * mm, unsigned long entry,
-                          unsigned long page, int isswap );
-static int unswap_by_move(unsigned short *, unsigned long, unsigned long,
-                         unsigned long);
-static int unswap_by_read(unsigned short *, unsigned long, unsigned long,
-                         unsigned long);
 static void *get_stram_region( unsigned long n_pages );
 static void free_stram_region( unsigned long offset, unsigned long n_pages
                               );
@@ -263,7 +254,7 @@ static int remove_region( BLOCK *block );
  * This init function is called very early by atari/config.c
  * It initializes some internal variables needed for stram_alloc()
  */
-__initfunc(void atari_stram_init( void ))
+void __init atari_stram_init(void)
 {
        int i;
 
@@ -294,7 +285,7 @@ __initfunc(void atari_stram_init( void ))
  * This function is called from mem_init() to reserve the pages needed for
  * ST-RAM management.
  */
-__initfunc(void atari_stram_reserve_pages( unsigned long start_mem ))
+void __init atari_stram_reserve_pages(unsigned long start_mem)
 {
 #ifdef CONFIG_STRAM_SWAP
        /* if max_swap_size is negative (i.e. no stram_swap= option given),
@@ -573,8 +564,7 @@ void atari_stram_free( void *addr )
  * Initialize ST-RAM swap device
  * (lots copied and modified from sys_swapon() in mm/swapfile.c)
  */
-__initfunc(static int swap_init( unsigned long start_mem,
-                                                                unsigned long swap_data ))
+static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
 {
        static struct dentry fake_dentry[3];
        struct swap_info_struct *p;
@@ -691,75 +681,64 @@ __initfunc(static int swap_init( unsigned long start_mem,
 /*
  * The swap entry has been read in advance, and we return 1 to indicate
  * that the page has been used or is no longer needed.
+ *
+ * Always set the resulting pte to be nowrite (the same as COW pages
+ * after one process has exited).  We don't know just how many PTEs will
+ * share this swap entry, so be cautious and let do_wp_page work out
+ * what to do if a write is requested later.
  */
-static inline int unswap_pte( struct vm_area_struct * vma, unsigned long
-                                                         address, pte_t *dir, unsigned long entry,
-                                                         unsigned long page, int isswap )
+static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
+                             address, pte_t *dir, unsigned long entry,
+                             unsigned long page /*, int isswap */)
 {
        pte_t pte = *dir;
 
        if (pte_none(pte))
-               return 0;
+               return;
        if (pte_present(pte)) {
-               struct page *pg;
-               unsigned long page_nr = MAP_NR(pte_page(pte));
-               unsigned long pg_swap_entry;
-
-               if (page_nr >= max_mapnr)
-                       return 0;
-               pg = mem_map + page_nr;
-               if (!(pg_swap_entry = in_swap_cache(pg)))
-                       return 0;
-               if (pg_swap_entry != entry)
-                       return 0;
-               if (isswap) {
-                       DPRINTK( "unswap_pte: page %08lx = entry %08lx was in swap cache; "
-                                        "exchanging to %08lx\n",
-                                        page_address(pg), entry, page );
-                       pg->offset = page;
-                       swap_free(entry);
-                       return 1;
-               }
-               else {
-                       DPRINTK( "unswap_pte: page %08lx = entry %08lx was in swap cache; "
-                                        "deleted there\n", page_address(pg), entry );
-                       delete_from_swap_cache(pg);
+               /* If this entry is swap-cached, then page must already
+                   hold the right address for any copies in physical
+                   memory */
+               if (pte_page(pte) != page)
+                       return;
+               if (0 /* isswap */)
+                       mem_map[MAP_NR(pte_page(pte))].offset = page;
+               else
+                       /* We will be removing the swap cache in a moment, so... */
                        set_pte(dir, pte_mkdirty(pte));
-                       free_page(page);
-                       return 1;
-               }
+               return;
        }
        if (pte_val(pte) != entry)
-               return 0;
+               return;
 
-       if (isswap) {
+       if (0 /* isswap */) {
                DPRINTK( "unswap_pte: replacing entry %08lx by %08lx", entry, page );
                set_pte(dir, __pte(page));
        }
        else {
                DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx",
                                 entry, page );
-               set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page,vma->vm_page_prot))));
+               set_pte(dir, pte_mkdirty(mk_pte(page,vma->vm_page_prot)));
+               atomic_inc(&mem_map[MAP_NR(page)].count);
                ++vma->vm_mm->rss;
        }
        swap_free(entry);
-       return 1;
 }
 
-static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir,
-                                                         unsigned long address, unsigned long size,
-                                                         unsigned long offset, unsigned long entry,
-                                                         unsigned long page, int isswap )
+static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
+                             unsigned long address, unsigned long size,
+                             unsigned long offset, unsigned long entry,
+                             unsigned long page /* , int isswap */)
 {
        pte_t * pte;
        unsigned long end;
 
        if (pmd_none(*dir))
-               return 0;
+               return;
        if (pmd_bad(*dir)) {
                printk("unswap_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
                pmd_clear(dir);
-               return 0;
+               return;
        }
        pte = pte_offset(dir, address);
        offset += address & PMD_MASK;
@@ -768,29 +747,27 @@ static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir,
        if (end > PMD_SIZE)
                end = PMD_SIZE;
        do {
-               if (unswap_pte( vma, offset+address-vma->vm_start, pte, entry, 
-                                               page, isswap ))
-                       return 1;
+               unswap_pte(vma, offset+address-vma->vm_start, pte, entry,
+                          page /* , isswap */);
                address += PAGE_SIZE;
                pte++;
        } while (address < end);
-       return 0;
 }
 
-static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir,
-                                                         unsigned long address, unsigned long size,
-                                                         unsigned long entry, unsigned long page,
-                                                         int isswap )
+static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
+                             unsigned long address, unsigned long size,
+                             unsigned long entry, unsigned long page
+                             /* , int isswap */)
 {
        pmd_t * pmd;
        unsigned long offset, end;
 
        if (pgd_none(*dir))
-               return 0;
+               return;
        if (pgd_bad(*dir)) {
                printk("unswap_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
                pgd_clear(dir);
-               return 0;
+               return;
        }
        pmd = pmd_offset(dir, address);
        offset = address & PGDIR_MASK;
@@ -799,53 +776,45 @@ static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir,
        if (end > PGDIR_SIZE)
                end = PGDIR_SIZE;
        do {
-               if (unswap_pmd( vma, pmd, address, end - address, offset, entry,
-                                               page, isswap ))
-                       return 1;
+               unswap_pmd(vma, pmd, address, end - address, offset, entry,
+                          page /* , isswap */);
                address = (address + PMD_SIZE) & PMD_MASK;
                pmd++;
        } while (address < end);
-       return 0;
 }
 
-static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir,
-                                          unsigned long entry, unsigned long page, int isswap )
+static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+                      unsigned long entry, unsigned long page
+                      /* , int isswap */)
 {
        unsigned long start = vma->vm_start, end = vma->vm_end;
 
-       while( start < end ) {
-               if (unswap_pgd( vma, pgdir, start, end - start, entry, page, isswap ))
-                       return 1;
+       while (start < end) {
+               unswap_pgd(vma, pgdir, start, end - start, entry, page
+                          /* , isswap */);
                start = (start + PGDIR_SIZE) & PGDIR_MASK;
                pgdir++;
        }
-       return 0;
 }
 
-static int unswap_process( struct mm_struct * mm, unsigned long entry, 
-                                                  unsigned long page, int isswap )
+static void unswap_process(struct mm_struct * mm, unsigned long entry, 
+                          unsigned long page /* , int isswap */)
 {
        struct vm_area_struct* vma;
-       int retval = 0;
 
        /*
         * Go through process' page directory.
         */
        if (!mm || mm == &init_mm)
-               return 0;
-       down(&mm->mmap_sem);
-       for( vma = mm->mmap; vma; vma = vma->vm_next ) {
+               return;
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
                pgd_t * pgd = pgd_offset(mm, vma->vm_start);
-               if (unswap_vma( vma, pgd, entry, page, isswap )) {
-                       retval = 1;
-                       break;
-               }
+               unswap_vma(vma, pgd, entry, page /* , isswap */);
        }
-       up(&mm->mmap_sem);
-       return retval;
 }
 
 
+#if 0
 static int unswap_by_move(unsigned short *map, unsigned long max,
                          unsigned long start, unsigned long n_pages)
 {
@@ -899,14 +868,17 @@ static int unswap_by_move(unsigned short *map, unsigned long max,
 #endif
 
                while( map[i] ) {
+                       read_lock(&tasklist_lock);
                        for_each_task(p) {
                                if (unswap_process( p->mm, SWP_ENTRY( stram_swap_type, i ),
                                                                        entry, 1 )) {
+                                       read_unlock(&tasklist_lock);
                                        map[j]++;
                                        goto repeat;
                                }
                        }
-                       if (map[i] && map[i] != 127) {
+                       read_unlock(&tasklist_lock);
+                       if (map[i] && map[i] != SWAP_MAP_MAX) {
                                printk( KERN_ERR "get_stram_region: ST-RAM swap page %lu "
                                                "not used by any process\n", i );
                                /* quit while loop and overwrite bad map entry */
@@ -932,13 +904,15 @@ static int unswap_by_move(unsigned short *map, unsigned long max,
        }
        return( 0 );
 }
+#endif
 
 static int unswap_by_read(unsigned short *map, unsigned long max,
                          unsigned long start, unsigned long n_pages)
 {
        struct task_struct *p;
-       unsigned long entry, page = 0;
+       unsigned long entry, page;
        unsigned long i;
+       struct page *page_map;
 
        DPRINTK( "unswapping %lu..%lu by reading in\n",
                         start, start+n_pages-1 );
@@ -949,43 +923,35 @@ static int unswap_by_read(unsigned short *map, unsigned long max,
                                        "reserved??\n", i );
                        continue;
                }
-               entry = SWP_ENTRY( stram_swap_type, i );
-               DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n",
-                                i, map[i], nr_swap_pages );
 
-               while( map[i] ) {
-                       if (!page && !(page = __get_free_page(GFP_KERNEL))) {
-                               printk( KERN_NOTICE "get_stram_region: out of memory\n" );
-                               return( -ENOMEM );
-                       }
-                       DPRINTK( "unswap: reading swap page %lu to %08lx\n", i, page );
-                       rw_swap_page( READ, entry, (char *)page, 1 );
-
-                       for_each_task(p) {
-                               if (unswap_process( p->mm, entry, page, 0 )) {
-                                       page = 0;
-#ifdef DO_PROC
-                                       stat_swap_force++;
-#endif
-                                       break;
-                               }
-                       }
-                       if (page) {
-                               /*
-                                * If we couldn't find an entry, there are several
-                                * possible reasons: someone else freed it first,
-                                * we freed the last reference to an overflowed entry,
-                                * or the system has lost track of the use counts.
-                                */
-                               if (map[i] && map[i] != SWAP_MAP_MAX)
-                                       printk( KERN_ERR "get_stram_region: swap entry %08lx "
-                                                       "not used by any process\n", entry );
-                               /* quit while loop and overwrite bad map entry */
-                               if (!map[i]) {
-                                       DPRINTK( "unswap: map[i] became 0\n" );
-                               }
-                               break;
+               if (map[i]) {
+                       entry = SWP_ENTRY(stram_swap_type, i);
+                       DPRINTK("unswap: map[i=%lu]=%u nr_swap=%u\n",
+                               i, map[i], nr_swap_pages);
+
+                       /* Get a page for the entry, using the existing
+                          swap cache page if there is one.  Otherwise,
+                          get a clean page and read the swap into it. */
+                       page_map = read_swap_cache(entry);
+                       if (page_map) {
+                               page = page_address(page_map);
+                               read_lock(&tasklist_lock);
+                               for_each_task(p)
+                                       unswap_process(p->mm, entry, page
+                                                      /* , 0 */);
+                               read_unlock(&tasklist_lock);
+                               shm_unuse(entry, page);
+                               /* Now get rid of the extra reference to
+                                  the temporary page we've been using. */
+                               if (PageSwapCache(page_map))
+                                       delete_from_swap_cache(page_map);
+                               __free_page(page_map);
+       #ifdef DO_PROC
+                               stat_swap_force++;
+       #endif
                        }
+                       else if (map[i])
+                               return -ENOMEM;
                }
 
                DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n",
@@ -998,9 +964,7 @@ static int unswap_by_read(unsigned short *map, unsigned long max,
                --nr_swap_pages;
        }
 
-       if (page)
-               free_page(page);
-       return( 0 );
+       return 0;
 }
 
 /*
@@ -1015,7 +979,9 @@ static void *get_stram_region( unsigned long n_pages )
        void *ret = NULL;
        
        DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages );
-       
+
+       down(&stram_swap_sem);
+
        /* disallow writing to the swap device now */
        stram_swap_info->flags = SWP_USED;
 
@@ -1026,9 +992,14 @@ static void *get_stram_region( unsigned long n_pages )
        DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",
                         start, region_free );
 
+#if 0
        err = ((total_free-region_free >= n_pages-region_free) ?
                   unswap_by_move( map, max, start, n_pages ) :
                   unswap_by_read( map, max, start, n_pages ));
+#else
+       err = unswap_by_read(map, max, start, n_pages);
+#endif
+
        if (err)
                goto end;
 
@@ -1036,6 +1007,7 @@ static void *get_stram_region( unsigned long n_pages )
   end:
        /* allow using swap device again */
        stram_swap_info->flags = SWP_WRITEOK;
+       up(&stram_swap_sem);
        DPRINTK( "get_stram_region: returning %p\n", ret );
        return( ret );
 }
@@ -1110,7 +1082,7 @@ static unsigned long find_free_region(unsigned long n_pages,
   start_over:
        /* increment tail until final window size reached, and count free pages */
        nfree = 0;
-       for( tail = head; tail-head < n_pages && tail < max-n_pages; ++tail ) {
+       for( tail = head; tail-head < n_pages && tail < max; ++tail ) {
                if (map[tail] == SWAP_MAP_BAD) {
                        head = tail+1;
                        goto start_over;
@@ -1165,7 +1137,7 @@ static unsigned long find_free_region(unsigned long n_pages,
 
 
 /* setup parameters from command line */
-__initfunc(void stram_swap_setup(char *str, int *ints))
+void __init stram_swap_setup(char *str, int *ints)
 {
        if (ints[0] >= 1)
                max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;
@@ -1262,7 +1234,7 @@ static struct file_operations stram_fops = {
        block_fsync             /* fsync */
 };
 
-__initfunc(int stram_device_init(void))
+int __init stram_device_init(void)
 {
 
     if (!MACH_IS_ATARI)
index e8adbdb5d85a1fe3cc8670cc93ea1c34d502f889..8fe84aecd4cc27cf43066a0afef14d0a9defb18b 100644 (file)
@@ -266,7 +266,7 @@ fi
 
 tristate 'Parallel printer support' CONFIG_M68K_PRINTER
 if [ "$CONFIG_ZORRO" = "y" ]; then
-  dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER
+  dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
 fi
 if [ "$CONFIG_AMIGA" = "y" ]; then
   tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
@@ -334,11 +334,6 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
   bool '   Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
   bool '   Software Watchdog' CONFIG_SOFT_WATCHDOG
 fi
-if [ "$CONFIG_VME" = "y" ]; then
-  define_bool CONFIG_UMISC y
-else
-  bool 'Support for user misc device modules' CONFIG_UMISC
-fi
 if [ "$CONFIG_ATARI" = "y" ]; then
   bool 'Enhanced Real Time Clock Support' CONFIG_RTC
 fi
index b32e6a1c99410232aac9c931e8192ddb0f2c7729..992d390c75f9d12e572197056c23b84169fb1dc2 100644 (file)
@@ -3,6 +3,6 @@
  */
 
 #define TS_MAGICKEY    0x5a5a5a5a
-#define TS_TSS 482
-#define TS_ESP0 502
-#define TS_FPU 506
+#define TS_TSS 478
+#define TS_ESP0 498
+#define TS_FPU 502
index f7c968486c192b0b4d7236a288fb1a356e42b497..fb9bac4000e4e2c7e7f81ad9864882f6e7005e94 100644 (file)
@@ -95,6 +95,9 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
+#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
+       apm_set_power_state(APM_STATE_OFF);
+#endif
 }
 
 void show_regs(struct pt_regs * regs)
index da91d32deedf09719ca2592ed669b18215ac773b..9888d83c13a7b5512c4d1159acdc59bca9dc6ce4 100644 (file)
@@ -450,10 +450,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        else
                                child->flags &= ~PF_TRACESYS;
                        child->exit_code = data;
-                       wake_up_process(child);
                        /* make sure the single step bit is not set. */
                        tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
                        put_reg(child, PT_SR, tmp);
+                       wake_up_process(child);
                        ret = 0;
                        goto out;
                }
@@ -469,11 +469,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = 0;
                        if (child->state == TASK_ZOMBIE) /* already dead */
                                goto out;
-                       wake_up_process(child);
                        child->exit_code = SIGKILL;
        /* make sure the single step bit is not set. */
                        tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
                        put_reg(child, PT_SR, tmp);
+                       wake_up_process(child);
                        goto out;
                }
 
@@ -487,9 +487,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
                        put_reg(child, PT_SR, tmp);
 
-                       wake_up_process(child);
                        child->exit_code = data;
        /* give it a chance to run. */
+                       wake_up_process(child);
                        ret = 0;
                        goto out;
                }
@@ -502,7 +502,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if ((unsigned long) data > _NSIG)
                                goto out;
                        child->flags &= ~(PF_PTRACED|PF_TRACESYS);
-                       wake_up_process(child);
                        child->exit_code = data;
                        write_lock_irqsave(&tasklist_lock, flags);
                        REMOVE_LINKS(child);
@@ -512,6 +511,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        /* make sure the single step bit is not set. */
                        tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
                        put_reg(child, PT_SR, tmp);
+                       wake_up_process(child);
                        ret = 0;
                        goto out;
                }
index 63b13a94dd1a6cc39b4ed11243da0ffae8976836..3125d06a2c52ddbdcfa3ce98fdce0813220a884c 100644 (file)
@@ -1197,7 +1197,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs)
 #else
        corefile[4] = '\0';
 #endif
-       dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC, 0600);
+       dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
        if (IS_ERR(dentry)) {
                inode = NULL;
                goto end_coredump;
index d749fd5bd66c88d25790b976126308bf58a79a34..dc898e300080cccc385ca39115232a13fdfd52dc 100644 (file)
@@ -106,7 +106,7 @@ do_aout32_core_dump(long signr, struct pt_regs * regs)
 #else
        corefile[4] = '\0';
 #endif
-       dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC, 0600);
+       dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
        if (IS_ERR(dentry)) {
                dentry = NULL;
                goto end_coredump;
index 35ad3b561ee08cc0920c6ed2ef6529998b9e5b60..9d6c4fb00edba190eb3d82ae1599ced9df8e0476 100644 (file)
@@ -1343,7 +1343,7 @@ static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
                if (acsi_wait_for_noIRQ( 20 ) &&
                    acsicmd_nodma( modesense_cmd, 0 ) &&
                    acsi_wait_for_IRQ( 3*HZ ) &&
-                   acsi_getstatus() == 0);
+                   acsi_getstatus() == 0)
                        break;
        }
        if (page == 4) {
index f958d62a00ff136400884d6153d203af3816de9a..1a0bf36dad9ba3139c58e9a1df8df8d671b83694 100644 (file)
@@ -4183,6 +4183,9 @@ __initfunc(int floppy_init(void))
                        continue;
                FDCS->rawcmd = 2;
                if (user_reset_fdc(-1,FD_RESET_ALWAYS,0)){
+                       /* free ioports reserved by floppy_grab_irq_and_dma() */
+                       release_region(FDCS->address, 6);
+                       release_region(FDCS->address+7, 1);
                        FDCS->address = -1;
                        FDCS->version = FDC_NONE;
                        continue;
@@ -4190,6 +4193,9 @@ __initfunc(int floppy_init(void))
                /* Try to determine the floppy controller type */
                FDCS->version = get_fdc_version();
                if (FDCS->version == FDC_NONE){
+                       /* free ioports reserved by floppy_grab_irq_and_dma() */
+                       release_region(FDCS->address, 6);
+                       release_region(FDCS->address+7, 1);
                        FDCS->address = -1;
                        continue;
                }
@@ -4211,6 +4217,12 @@ __initfunc(int floppy_init(void))
        if (have_no_fdc) 
        {
                DPRINT("no floppy controllers found\n");
+               floppy_tq.routine = (void *)(void *) empty;
+               mark_bh(IMMEDIATE_BH);
+               schedule();
+               if (usage_count)
+                       floppy_release_irq_and_dma();
+               blk_dev[MAJOR_NR].request_fn = NULL;
                unregister_blkdev(MAJOR_NR,"fd");               
        }
        return have_no_fdc;
index e56616a773abad97d536ada55601f7823f162798..4e165bbd0dba68a61e594d38a29f31532acc377d 100644 (file)
@@ -109,20 +109,16 @@ u_int dma_arb_level;              /* DMA arbitration level */
 
 static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open = NULL;
 int no_int_yet;
-static int access_count[MAX_HD] =
-{0,};
-static char ps2esdi_valid[MAX_HD] =
-{0,};
-static int ps2esdi_sizes[MAX_HD << 6] =
-{0,};
-static int ps2esdi_blocksizes[MAX_HD << 6] =
-{0,};
+static int access_count[MAX_HD] = {0,};
+static char ps2esdi_valid[MAX_HD] = {0,};
+static int ps2esdi_sizes[MAX_HD << 6] = {0,};
+static int ps2esdi_blocksizes[MAX_HD << 6] = {0,};
 static int ps2esdi_drives = 0;
 static struct hd_struct ps2esdi[MAX_HD << 6];
 static u_short io_base;
-static struct timer_list esdi_timer =
-{NULL, NULL, 0, 0L, ps2esdi_reset_timer};
+static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer};
 static int reset_status;
+static int ps2esdi_slot = -1;
 int tp720esdi = 0;             /* Is it Integrated ESDI of ThinkPad-720? */
 
 struct ps2esdi_i_struct {
@@ -198,6 +194,51 @@ __initfunc(int ps2esdi_init(void))
 
 }                              /* ps2esdi_init */
 
+#ifdef MODULE
+
+int cyl[2] = {-1,-1};
+int head[2] = {-1, -1};
+int sect[2] = {-1, -1};
+
+MODULE_PARM(tp720esdi, "i");
+MODULE_PARM(cyl, "i");
+MODULE_PARM(head, "i");
+MODULE_PARM(track, "i");
+
+int init_module(void) {
+       int drive;
+
+       for(drive = 0; drive <= 1; drive++) {
+               struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
+
+               if (cyl[drive] != -1) {
+                       info->cyl = info->lzone = cyl[drive];
+                       info->wpcom = 0;
+               }
+               if (head[drive] != -1) {
+                       info->head = head[drive];
+                       info->ctl = (head[drive] > 8 ? 8 : 0);
+               }
+               if (sect[drive] != -1) info->sect = sect[drive];
+       }
+       return ps2esdi_init();
+}
+
+void
+cleanup_module(void)
+{
+       if(ps2esdi_slot)
+       {
+               mca_mark_as_unused(ps2esdi_slot);
+               mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
+       }
+       release_region(io_base, 4);
+       free_dma(dma_arb_level);
+       free_irq(PS2ESDI_IRQ, NULL)
+       unregister_blkdev(MAJOR_NR, "ed");
+}
+#endif /* MODULE */
+
 /* handles boot time command line parameters */
 __initfunc(void tp720_setup(char *str, int *ints))
 {
@@ -289,6 +330,8 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
                return;
        }
 
+       ps2esdi_slot = slot;
+       mca_mark_as_used(slot);
        mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
 
        /* Found the slot - read the POS register 2 to get the necessary
@@ -383,6 +426,9 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
        }
        for (i = 0; i < (MAX_HD << 6); i++)
                ps2esdi_blocksizes[i] = 1024;
+
+       request_dma(dma_arb_level, "ed");
+       request_region(io_base, 4, "ed");
        blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
 }                              /* ps2esdi_geninit */
 
@@ -511,7 +557,7 @@ static void reset_ctrl(void)
                printk("%s: hard reset...\n", DEVICE_NAME);
                outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
                expire = jiffies + 200;
-               while (jiffies < expire);
+               while (time_before(jiffies, expire));
                outb_p(1, ESDI_CONTROL);
        }                       /* hard reset */
 
@@ -588,7 +634,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
        outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
 
        /* do not write to the controller, if it is busy */
-       for (i = jiffies + ESDI_STAT_TIMEOUT; (i > jiffies) && (inb(ESDI_STATUS) &
+       for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) &
                                                          STATUS_BUSY););
 
 #if 0
@@ -611,7 +657,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
        for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
                status = inb(ESDI_STATUS);
                for (j = jiffies + ESDI_STAT_TIMEOUT;
-                    (j > jiffies) && (status & STATUS_BUSY) &&
+                    time_after(j, jiffies) && (status & STATUS_BUSY) &&
                   (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
                if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
 #if 0
index 7e5d4f99cb0f19dc3f489652433543becce51d7c..2ea4bf393d7adf4344db5e52231346d425f23434 100644 (file)
@@ -108,9 +108,7 @@ static XD_SIGNATURE xd_sigs[] __initdata = {
        { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
        { 0x000B,"CRD18A   Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Todd Fries, tfries@umr.edu */
        { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */
-       { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
        { 0x0008,"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002-27X" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
-       { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
        { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
        { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
        { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
@@ -589,7 +587,7 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
        int success;
 
        xdc_busy = 1;
-       while ((success = ((inb(port) & mask) != flags)) && (jiffies < expiry)) {
+       while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
                xd_timer.expires = jiffies;
                cli();
                add_timer(&xd_timer);
@@ -1169,7 +1167,7 @@ int init_module(void)
                for (i = 4; i > 0; i--)
                        if(((xd[i] = xd[i-1]) >= 0) && !count)
                                count = i;
-               if((xd[0] = count));
+               if((xd[0] = count))
                        xd_setup(NULL, xd);
                xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 });
                if (!xd_drives) {
index 60845a3cb9487b51291d124ff212ac3d0b05f6ef..121550cc3d66cbb99eb012517ac6b05d14111699 100644 (file)
@@ -787,23 +787,13 @@ static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
  *     May be we could use a simple count loop w/ jumps to itself, but
  *     I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
 {
-    unsigned long tout = jiffies + jifs;
-    if (jifs < 0) return;
-
-       /* If loaded during kernel boot no *_sleep_on is
-        * allowed! */
-    if (current->pid == 0) {
-               while (jiffies < tout) {
-            schedule_timeout(0);
-        }
-    } else {
-        current->timeout = tout;
-               xtrace(SLEEP, "*** delay: sleepq\n");
-               interruptible_sleep_on(&stuff->sleepq);
-               xtrace(SLEEP, "delay awoken\n");
-               if (signal_pending(current)) {
-                       xtrace(SLEEP, "got signal\n");
-               }
+       if (jifs < 0) return;
+
+       xtrace(SLEEP, "*** delay: sleepq\n");
+       interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
+       xtrace(SLEEP, "delay awoken\n");
+       if (signal_pending(current)) {
+               xtrace(SLEEP, "got signal\n");
        }
 }
 
index 6716c47b18d3b0603ebbeaf66226bd0145046bb5..3101c31ecb3c564aecbb98025cbfa921fd80c8b8 100644 (file)
@@ -403,7 +403,8 @@ static struct i2c_bus bttv_i2c_bus_template =
 
 struct tvcard
 {
-        int inputs;
+        int video_inputs;
+        int audio_inputs;
         int tuner;
         int svhs;
         u32 gpiomask;
@@ -415,30 +416,37 @@ struct tvcard
 static struct tvcard tvcards[] = 
 {
         /* default */
-        { 3, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
+        { 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
         /* MIRO */
-        { 4, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}},
+        { 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}},
         /* Hauppauge */
-        { 3, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
+        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
        /* STB */
-        { 3, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}},
+        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}},
        /* Intel??? */
-        { 3, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
+        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
        /* Diamond DTV2000 */
-        { 3, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},
+        { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},
        /* AVerMedia TVPhone */
-        { 3, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
+        { 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
         /* Matrix Vision MV-Delta */
-        { 5,-1, 3, 0, { 2, 3, 1, 0, 0}},
+        { 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0}},
         /* Fly Video II */
-        { 3, 0, 2, 0xc00, { 2, 3, 1, 1}, 
+        { 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1}, 
         {0, 0xc00, 0x800, 0x400, 0xc00, 0}},
         /* TurboTV */
-        { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
+        { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
        /* Newer Hauppauge (bt878) */
-       { 3, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},
+       { 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},
        /* MIRO PCTV pro */
-       { 3, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
+       { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
+       /* ADS Technologies Channel Surfer TV (and maybe TV+FM) */
+       {
+        3, 4, 0, 2, 0x0F,
+        { 0x02, 0x03, 0x01, 0x01},
+        { 0x0D, 0x0E, 0x0B, 0x07, 0x00, 0x00},
+        0x00
+       },
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -612,7 +620,7 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input)
        btand(~(3<<5), BT848_IFORM);
        mdelay(10); 
 
-               input %= tvcards[btv->type].inputs;
+               input %= tvcards[btv->type].video_inputs;
        if (input==tvcards[btv->type].svhs) 
        {
                btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
@@ -1304,7 +1312,7 @@ static void bttv_close(struct video_device *dev)
        struct bttv *btv=(struct bttv *)dev;
   
        btv->user--;
-       audio(btv, AUDIO_MUTE);
+       audio(btv, AUDIO_INTERN);
        btv->cap&=~3;
        bt848_set_risc_jmps(btv);
 
@@ -1383,8 +1391,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                VID_TYPE_CLIPPING|
                                VID_TYPE_FRAMERAM|
                                VID_TYPE_SCALES;
-                       b.channels = tvcards[btv->type].inputs;
-                       b.audios = tvcards[btv->type].inputs;
+                       b.channels = tvcards[btv->type].video_inputs;
+                       b.audios = tvcards[btv->type].audio_inputs;
                        b.maxwidth = 768;
                        b.maxheight = 576;
                        b.minwidth = 32;
@@ -1402,7 +1410,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        v.tuners=0;
                        v.type=VIDEO_TYPE_CAMERA;
                        v.norm = btv->win.norm;
-                        if (v.channel>=tvcards[btv->type].inputs)
+                        if (v.channel>=tvcards[btv->type].video_inputs)
                                 return -EINVAL;
                         if(v.channel==tvcards[btv->type].tuner) 
                         {
@@ -1429,7 +1437,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        if(copy_from_user(&v, arg,sizeof(v)))
                                return -EFAULT;
                         
-                        if (v.channel>tvcards[btv->type].inputs)
+                        if (v.channel>=tvcards[btv->type].video_inputs)
                                 return -EINVAL;
                        bt848_muxsel(btv, v.channel);
                        if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
@@ -1710,7 +1718,10 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        if(v.flags&VIDEO_AUDIO_MUTE)
                                audio(btv, AUDIO_MUTE);
                        /* One audio source per tuner */
-                       if(v.audio!=0)
+                       /* if(v.audio!=0) */
+                       /* Nope... I have three on my ADSTech TV card. The*/
+                       /* ADSTech TV+FM prolly has 4 <rriggs@tesser.com> */
+                       if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
                                return -EINVAL;
                        bt848_muxsel(btv,v.audio);
                        if(!(v.flags&VIDEO_AUDIO_MUTE))
@@ -2456,8 +2467,13 @@ static void idcard(int i)
                        printk("MATRIX-Vision\n");
                        strcat(btv->video_dev.name,"(MATRIX-Vision)");
                        break;
+               case BTTV_ADSTECH_TV:
+                       printk("ADSTech Channel Surfer TV\n");
+                       strcat(btv->video_dev.name,"(ADSTech Channel Surfer TV)");
+                       btv->tuner_type=8;
+                       break;
        }
-       audio(btv, AUDIO_MUTE);
+       audio(btv, AUDIO_INTERN);
 }
 
 
index 27a4a25db05b1cb79c6611d6ff71636ee1c05b3e..f780de12b724d8378c0281101b3bafeef382b6f6 100644 (file)
@@ -186,6 +186,7 @@ struct bttv
 #define BTTV_TURBOTV       0x09
 #define BTTV_HAUPPAUGE878  0x0a
 #define BTTV_MIROPRO       0x0b
+#define BTTV_ADSTECH_TV    0x0c
 
 #define AUDIO_TUNER        0x00
 #define AUDIO_RADIO        0x01
index c126d05a838439d1454aa4c86faf779e4387f6fb..9fb9269f83394fd4fb467c02083eace1cb6b64b2 100644 (file)
@@ -388,9 +388,10 @@ int fdc_interrupt_wait(unsigned int time)
        struct wait_queue wait = {current, NULL};
        sigset_t old_sigmask;   
        static int resetting = 0;
-       TRACE_FUN(ft_t_fdc_dma);
        long timeout;
 
+       TRACE_FUN(ft_t_fdc_dma);
+
 #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16)
        if (waitqueue_active(&ftape_wait_intr)) {
                TRACE_ABORT(-EIO, ft_t_err, "error: nested call");
index 13594d02a1dd687baa4e7f27c19489556b73bffd..bafc7e1a9c52976b9bd6c4c473e82f1b470c2c9b 100644 (file)
@@ -122,9 +122,8 @@ void *zft_kmalloc(size_t size)
        void *new;
 
        while ((new = kmalloc(size, GFP_KERNEL)) == NULL) {
-               current->timeout = HZ/10;
                current->state   = TASK_INTERRUPTIBLE;
-               schedule();
+               schedule_timeout(HZ/10);
        }
        memset(new, 0, size);
        used_memory += size;
index 1b2da0bb739388ab5678f523797fa2660e7e79bb..8886b59be21392d0c5bf1a719e70ebe375eb46ec 100644 (file)
@@ -77,7 +77,7 @@ extern __inline__ u8 mvv_read(u8 index)
        return inb(data_port);
 }
 
-extern int i2c_stat(u8 slave)
+static int pms_i2c_stat(u8 slave)
 {
        int counter;
        int i;
@@ -116,7 +116,7 @@ extern int i2c_stat(u8 slave)
        return inb(data_port);          
 }
 
-int i2c_write(u16 slave, u16 sub, u16 data)
+static int pms_i2c_write(u16 slave, u16 sub, u16 data)
 {
        int skip=0;
        int count;
@@ -166,7 +166,7 @@ int i2c_write(u16 slave, u16 sub, u16 data)
        return count;
 }
 
-int i2c_read(int slave, int sub)
+static int pms_i2c_read(int slave, int sub)
 {
        int i=0;
        for(i=0;i<i2c_count;i++)
@@ -178,13 +178,13 @@ int i2c_read(int slave, int sub)
 }
 
 
-void i2c_andor(int slave, int sub, int and, int or)
+static void pms_i2c_andor(int slave, int sub, int and, int or)
 {
        u8 tmp; 
        
-       tmp=i2c_read(slave, sub);
+       tmp=pms_i2c_read(slave, sub);
        tmp = (tmp&and)|or;
-       i2c_write(slave, sub, tmp);
+       pms_i2c_write(slave, sub, tmp);
 }
 
 /*
@@ -202,13 +202,13 @@ static void pms_hue(short hue)
        switch(decoder)
        {
                case MOTOROLA:
-                       i2c_write(0x8A, 0x00, hue);
+                       pms_i2c_write(0x8A, 0x00, hue);
                        break;
                case PHILIPS2:
-                       i2c_write(0x8A, 0x07, hue);
+                       pms_i2c_write(0x8A, 0x07, hue);
                        break;
                case PHILIPS1:
-                       i2c_write(0x42, 0x07, hue);
+                       pms_i2c_write(0x42, 0x07, hue);
                        break;
        }
 }
@@ -218,10 +218,10 @@ static void pms_colour(short colour)
        switch(decoder)
        {
                case MOTOROLA:
-                       i2c_write(0x8A, 0x00, colour);
+                       pms_i2c_write(0x8A, 0x00, colour);
                        break;
                case PHILIPS1:
-                       i2c_write(0x42, 012, colour);
+                       pms_i2c_write(0x42, 012, colour);
                        break;
        }
 }
@@ -232,10 +232,10 @@ static void pms_contrast(short contrast)
        switch(decoder)
        {
                case MOTOROLA:
-                       i2c_write(0x8A, 0x00, contrast);
+                       pms_i2c_write(0x8A, 0x00, contrast);
                        break;
                case PHILIPS1:
-                       i2c_write(0x42, 0x13, contrast);
+                       pms_i2c_write(0x42, 0x13, contrast);
                        break;
        }
 }
@@ -245,12 +245,12 @@ static void pms_brightness(short brightness)
        switch(decoder)
        {
                case MOTOROLA:
-                       i2c_write(0x8A, 0x00, brightness);
-                       i2c_write(0x8A, 0x00, brightness);
-                       i2c_write(0x8A, 0x00, brightness);
+                       pms_i2c_write(0x8A, 0x00, brightness);
+                       pms_i2c_write(0x8A, 0x00, brightness);
+                       pms_i2c_write(0x8A, 0x00, brightness);
                        break;
                case PHILIPS1:
-                       i2c_write(0x42, 0x19, brightness);
+                       pms_i2c_write(0x42, 0x19, brightness);
                        break;
        }
 }
@@ -271,20 +271,20 @@ static void pms_format(short format)
        switch(format)
        {
                case 0: /* Auto */
-                       i2c_andor(target, 0x0D, 0xFE,0x00);
-                       i2c_andor(target, 0x0F, 0x3F,0x80);
+                       pms_i2c_andor(target, 0x0D, 0xFE,0x00);
+                       pms_i2c_andor(target, 0x0F, 0x3F,0x80);
                        break;
                case 1: /* NTSC */
-                       i2c_andor(target, 0x0D, 0xFE, 0x00);
-                       i2c_andor(target, 0x0F, 0x3F, 0x40);
+                       pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
+                       pms_i2c_andor(target, 0x0F, 0x3F, 0x40);
                        break;
                case 2: /* PAL */
-                       i2c_andor(target, 0x0D, 0xFE, 0x00);
-                       i2c_andor(target, 0x0F, 0x3F, 0x00);
+                       pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
+                       pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
                        break;
                case 3: /* SECAM */
-                       i2c_andor(target, 0x0D, 0xFE, 0x01);
-                       i2c_andor(target, 0x0F, 0x3F, 0x00);
+                       pms_i2c_andor(target, 0x0D, 0xFE, 0x01);
+                       pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
                        break;
        }
 }
@@ -302,12 +302,12 @@ static void pms_hstart(short start)
        switch(decoder)
        {
                case PHILIPS1:
-                       i2c_write(0x8A, 0x05, start);
-                       i2c_write(0x8A, 0x18, start);
+                       pms_i2c_write(0x8A, 0x05, start);
+                       pms_i2c_write(0x8A, 0x18, start);
                        break;
                case PHILIPS2:
-                       i2c_write(0x42, 0x05, start);
-                       i2c_write(0x42, 0x18, start);
+                       pms_i2c_write(0x42, 0x05, start);
+                       pms_i2c_write(0x42, 0x18, start);
                        break;
        }
 }
@@ -319,94 +319,94 @@ static void pms_hstart(short start)
 static void pms_bandpass(short pass)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4);
+               pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4);
+               pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4);
 }
 
 static void pms_antisnow(short snow)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2);
+               pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2);
+               pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2);
 }
 
 static void pms_sharpness(short sharp)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03);
+               pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x06, 0xFC, sharp&0x03);
+               pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03);
 }
 
 static void pms_chromaagc(short agc)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5);
+               pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5);
+               pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5);
 }
 
 static void pms_vertnoise(short noise)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x10, 0xFC, noise&3);
+               pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x10, 0xFC, noise&3);
+               pms_i2c_andor(0x42, 0x10, 0xFC, noise&3);
 }
 
 static void pms_forcecolour(short colour)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7);
+               pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7);
+               pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7);
 }
 
 static void pms_antigamma(short gamma)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7);
+               pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7);
+               pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7);
 }
 
 static void pms_prefilter(short filter)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6);
+               pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6);
+               pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6);
 }
 
 static void pms_hfilter(short filter)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5);
+               pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5);
+               pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5);
 }
 
 static void pms_vfilter(short filter)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5);
+               pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5);
+               pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5);
 }
 
 static void pms_killcolour(short colour)
 {
        if(decoder==PHILIPS2)
        {
-               i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
-               i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
+               pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
+               pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
        }
        else if(decoder==PHILIPS1)
        {
-               i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
-               i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
+               pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
+               pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
        }
 }
 
@@ -414,11 +414,11 @@ static void pms_chromagain(short chroma)
 {
        if(decoder==PHILIPS2)
        {
-               i2c_write(0x8A, 0x11, chroma);
+               pms_i2c_write(0x8A, 0x11, chroma);
        }
        else if(decoder==PHILIPS1)
        {
-               i2c_write(0x42, 0x11, chroma);
+               pms_i2c_write(0x42, 0x11, chroma);
        }
 }
 
@@ -444,9 +444,9 @@ static void pms_vstart(short start)
 static void pms_secamcross(short cross)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5);
+               pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5);
+               pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5);
 }
 
 
@@ -454,13 +454,13 @@ static void pms_swsense(short sense)
 {
        if(decoder==PHILIPS2)
        {
-               i2c_write(0x8A, 0x0A, sense);
-               i2c_write(0x8A, 0x0B, sense);
+               pms_i2c_write(0x8A, 0x0A, sense);
+               pms_i2c_write(0x8A, 0x0B, sense);
        }
        else if(decoder==PHILIPS1)
        {
-               i2c_write(0x42, 0x0A, sense);
-               i2c_write(0x42, 0x0B, sense);
+               pms_i2c_write(0x42, 0x0A, sense);
+               pms_i2c_write(0x42, 0x0B, sense);
        }
 }
 
@@ -613,9 +613,9 @@ static void pms_resolution(short width, short height)
 static void pms_vcrinput(short input)
 {
        if(decoder==PHILIPS2)
-               i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7);
+               pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7);
        else if(decoder==PHILIPS1)
-               i2c_andor(0x42,0x0D,0x7F,(input&1)<<7);
+               pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7);
 }
 
 
@@ -954,13 +954,13 @@ static int init_mediavision(void)
        
        
        id=mvv_read(3);
-       decst=i2c_stat(0x43);
+       decst=pms_i2c_stat(0x43);
        
        if(decst!=-1)
                idec=2;
-       else if(i2c_stat(0xb9)!=-1)
+       else if(pms_i2c_stat(0xb9)!=-1)
                idec=3;
-       else if(i2c_stat(0x8b)!=-1)
+       else if(pms_i2c_stat(0x8b)!=-1)
                idec=1;
        else 
                idec=0;
@@ -983,19 +983,19 @@ static int init_mediavision(void)
        for(i=0;i<0x19;i++)
        {
                if(i2c_defs[i]==0xFF)
-                       i2c_andor(0x8A, i, 0x07,0x00);
+                       pms_i2c_andor(0x8A, i, 0x07,0x00);
                else
-                       i2c_write(0x8A, i, i2c_defs[i]);
+                       pms_i2c_write(0x8A, i, i2c_defs[i]);
        }
        
-       i2c_write(0xB8,0x00,0x12);
-       i2c_write(0xB8,0x04,0x00);
-       i2c_write(0xB8,0x07,0x00);
-       i2c_write(0xB8,0x08,0x00);
-       i2c_write(0xB8,0x09,0xFF);
-       i2c_write(0xB8,0x0A,0x00);
-       i2c_write(0xB8,0x0B,0x10);
-       i2c_write(0xB8,0x10,0x03);
+       pms_i2c_write(0xB8,0x00,0x12);
+       pms_i2c_write(0xB8,0x04,0x00);
+       pms_i2c_write(0xB8,0x07,0x00);
+       pms_i2c_write(0xB8,0x08,0x00);
+       pms_i2c_write(0xB8,0x09,0xFF);
+       pms_i2c_write(0xB8,0x0A,0x00);
+       pms_i2c_write(0xB8,0x0B,0x10);
+       pms_i2c_write(0xB8,0x10,0x03);
        
        mvv_write(0x01, 0x00);
        mvv_write(0x05, 0xA0);
@@ -1037,7 +1037,7 @@ static void shutdown_mediavision(void)
 #ifdef MODULE
 int init_module(void)
 #else
-void init_pms_cards(void)
+int init_pms_cards(struct video_init *v)
 #endif
 {
        printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
index 27c7d4c187954109528ec6943cf8055621ea281c..bc49cb80b01a2d52aac886b9ddf16557a2378f1e 100644 (file)
@@ -666,6 +666,15 @@ static long saa5249_read(struct video_device *v, char *buf, unsigned long l, int
        return -EINVAL;
 }
 
+int init_saa_5249(struct video_init *v)
+{
+       printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n",
+                       VTX_VER_MAJ, VTX_VER_MIN);
+       i2c_register_driver(&i2c_driver_videotext);
+
+       return 0;
+}
+
 static struct video_device saa_template=
 {
        IF_NAME,
@@ -684,15 +693,15 @@ static struct video_device saa_template=
        0
 };
 
+#ifdef MODULE
+
 /*
  *     Routines for loadable modules
  */
 
 int init_module(void) 
 {
-       printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n",
-                       VTX_VER_MAJ, VTX_VER_MIN);
-       i2c_register_driver(&i2c_driver_videotext);
+       init_saa_5249(NULL);
        return 0;
 }
 
@@ -701,3 +710,5 @@ void cleanup_module(void)
 {
        i2c_unregister_driver(&i2c_driver_videotext);
 }
+
+#endif
index fa537051210c1c6cdd9735303e94598807ef242c..7f7471e19b831665f999e795314452a7963fb891 100644 (file)
@@ -70,6 +70,8 @@ static struct tunertype tuners[] = {
                16*157.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,732},
        {"TEMIC PAL_I", TEMIC, PAL_I,
                16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
+       {"Temic 4036 FY5 NTSC", TEMIC, NTSC,
+               16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},             
 };
 
 /* ---------------------------------------------------------------------- */
index 3fb77de47a7a74e90088d07a230c1c704481b6f4..439cc530d7288f5ddcb79d7ba6225b9698ff368d 100644 (file)
@@ -30,6 +30,7 @@
 #define TUNER_PHILIPS_PAL   5
 #define TUNER_TEMIC_NTSC    6
 #define TUNER_TEMIC_PAL_I   7
+#define TUNER_TEMIC_4036FY5_NTSC       8
 
 #define NOTUNER 0
 #define PAL     1
index a8d335a645f6d807437bd3aea3b8ba23a881be21..def6e70391f13b77438028c5f7019344248b9210 100644 (file)
@@ -68,6 +68,9 @@ extern int fmi_init(struct video_init *);
 #ifdef CONFIG_RADIO_MIROPCM20
 extern int pcm20_init(struct video_init *);
 #endif
+#ifdef CONFIG_VIDEO_PMS
+extern int init_pms_cards(struct video_init *);
+#endif
 
 static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
new file mode 100644 (file)
index 0000000..b74ca51
--- /dev/null
@@ -0,0 +1,1499 @@
+/* 3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux. */
+/*
+       Written 1997-1998 by Donald Becker.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+*/
+
+static char *version = "3c515.c:v0.99 4/7/98 becker@cesdis.gsfc.nasa.gov\n";
+#define CORKSCREW 1
+
+/* "Knobs" that adjust features and parameters. */
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+   Setting to > 1512 effectively disables this feature. */
+static const int rx_copybreak = 200;
+/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
+static const int mtu = 1500;
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Enable the automatic media selection code -- usually set. */
+#define AUTOMEDIA 1
+
+/* Allow the use of fragment bus master transfers instead of only
+   programmed-I/O for Vortex cards.  Full-bus-master transfers are always
+   enabled by default on Boomerang cards.  If VORTEX_BUS_MASTER is defined,
+   the feature may be turned on using 'options'. */
+#define VORTEX_BUS_MASTER
+
+/* A few values that may be tweaked. */
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE   16
+#define RX_RING_SIZE   16
+#define PKT_BUF_SZ             1536                    /* Size of each temporary Rx buffer.*/
+
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#if (LINUX_VERSION_CODE >= 0x10344)
+#define NEW_MULTICAST
+#include <linux/delay.h>
+#else
+#define udelay(microsec)       do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#endif
+
+/* Kernel version compatibility functions. */
+#define RUN_AT(x) (jiffies + (x))
+#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
+#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#elif defined(MODULE)
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+#endif
+
+/* "Knobs" for adjusting internal parameters. */
+/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
+#define DRIVER_DEBUG 1
+/* Some values here only for performance evaluation and path-coverage
+   debugging. */
+static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0;
+
+/* Number of times to check to see if the Tx FIFO has space, used in some
+   limited cases. */
+#define WAIT_TX_AVAIL 200
+
+/* Operational parameter that usually are not changed. */
+#define TX_TIMEOUT  40         /* Time in jiffies before concluding Tx hung */
+
+/* The size here is somewhat misleading: the Corkscrew also uses the ISA
+   aliased registers at <base>+0x400.
+   */
+#define CORKSCREW_TOTAL_SIZE 0x20
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry tc515_drv =
+{"3c515", tc515_probe, CORKSCREW_TOTAL_SIZE, NULL};
+#endif
+
+#ifdef DRIVER_DEBUG
+int vortex_debug = DRIVER_DEBUG;
+#else
+int vortex_debug = 1;
+#endif
+
+#define CORKSCREW_ID 10
+
+/*
+                               Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the 3Com 3c515 ISA Fast EtherLink XL,
+3Com's ISA bus adapter for Fast Ethernet.  Due to the unique I/O port layout,
+it's not practical to integrate this driver with the other EtherLink drivers.
+
+II. Board-specific settings
+
+The Corkscrew has an EEPROM for configuration, but no special settings are
+needed for Linux.
+
+III. Driver operation
+
+The 3c515 series use an interface that's very similar to the 3c900 "Boomerang"
+PCI cards, with the bus master interface extensively modified to work with
+the ISA bus.
+
+The card is capable of full-bus-master transfers with separate
+lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
+DEC Tulip and Intel Speedo3.
+
+This driver uses a "RX_COPYBREAK" scheme rather than a fixed intermediate
+receive buffer.  This scheme allocates full-sized skbuffs as receive
+buffers.  The value RX_COPYBREAK is used as the copying breakpoint: it is
+chosen to trade-off the memory wasted by passing the full-sized skbuff to
+the queue layer for all frames vs. the copying cost of copying a frame to a
+correctly-sized skbuff.
+
+
+IIIC. Synchronization
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+IV. Notes
+
+Thanks to Terry Murphy of 3Com for providing documentation and a development
+board.
+
+The names "Vortex", "Boomerang" and "Corkscrew" are the internal 3Com
+project names.  I use these names to eliminate confusion -- 3Com product
+numbers and names are very similar and often confused.
+
+The new chips support both ethernet (1.5K) and FDDI (4.5K) frame sizes!
+This driver only supports ethernet frames because of the recent MTU limit
+of 1.5K, but the changes to support 4.5K are minimal.
+*/
+
+/* Operational definitions.
+   These are not used by other compilation units and thus are not
+   exported in a ".h" file.
+
+   First the windows.  There are eight register windows, with the command
+   and status registers available in each.
+   */
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable.
+   Note that 11 parameters bits was fine for ethernet, but the new chips
+   can handle FDDI length frames (~4500 octets) and now parameters count
+   32-bit 'Dwords' rather than octets. */
+
+enum vortex_cmd {
+       TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
+       RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
+       UpStall = 6<<11, UpUnstall = (6<<11)+1,
+       DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
+       RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
+       FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
+       SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
+       SetTxThreshold = 18<<11, SetTxStart = 19<<11,
+       StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
+       StatsDisable = 22<<11, StopCoax = 23<<11,};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+       RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
+
+/* Bits in the general status register. */
+enum vortex_status {
+       IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+       TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+       IntReq = 0x0040, StatsFull = 0x0080,
+       DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
+       DMAInProgress = 1<<11,                  /* DMA controller is still busy.*/
+       CmdInProgress = 1<<12,                  /* EL3_CMD is still busy.*/
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+   On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
+enum Window1 {
+       TX_FIFO = 0x10,  RX_FIFO = 0x10,  RxErrors = 0x14,
+       RxStatus = 0x18,  Timer=0x1A, TxStatus = 0x1B,
+       TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
+};
+enum Window0 {
+  Wn0IRQ = 0x08,
+#if defined(CORKSCREW)
+       Wn0EepromCmd = 0x200A,          /* Corkscrew EEPROM command register. */
+       Wn0EepromData = 0x200C,         /* Corkscrew EEPROM results register. */
+#else
+       Wn0EepromCmd = 10,              /* Window 0: EEPROM command register. */
+       Wn0EepromData = 12,             /* Window 0: EEPROM results register. */
+#endif
+};
+enum Win0_EEPROM_bits {
+       EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
+       EEPROM_EWENB = 0x30,            /* Enable erasing/writing for 10 msec. */
+       EEPROM_EWDIS = 0x00,            /* Disable EWENB before 10 msec timeout. */
+};
+/* EEPROM locations. */
+enum eeprom_offset {
+       PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
+       EtherLink3ID=7, };
+
+enum Window3 {                 /* Window 3: MAC/config bits. */
+       Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+};
+union wn3_config {
+       int i;
+       struct w3_config_fields {
+               unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
+               int pad8:8;
+               unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;
+               int pad24:7;
+       } u;
+};
+
+enum Window4 {
+       Wn4_NetDiag = 6, Wn4_Media = 10,                /* Window 4: Xcvr/media bits. */
+};
+enum Win4_Media_bits {
+       Media_SQE = 0x0008,             /* Enable SQE error counting for AUI. */
+       Media_10TP = 0x00C0,    /* Enable link beat and jabber for 10baseT. */
+       Media_Lnk = 0x0080,             /* Enable just link beat for 100TX/100FX. */
+       Media_LnkBeat = 0x0800,
+};
+enum Window7 {                                 /* Window 7: Bus Master control. */
+       Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+};
+/* Boomerang-style bus master control registers.  Note ISA aliases! */
+enum MasterCtrl {
+       PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen = 0x40c,
+       TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
+};
+
+/* The Rx and Tx descriptor lists.
+   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
+   alignment contraint on tx_ring[] and rx_ring[]. */
+struct boom_rx_desc {
+       u32 next;
+       s32 status;
+       u32 addr;
+       s32 length;
+};
+/* Values for the Rx status entry. */
+enum rx_desc_status {
+       RxDComplete=0x00008000, RxDError=0x4000,
+       /* See boomerang_rx() for actual error bits */
+};
+
+struct boom_tx_desc {
+       u32 next;
+       s32 status;
+       u32 addr;
+       s32 length;
+};
+
+struct vortex_private {
+       char devname[8];                        /* "ethN" string, also for kernel debug. */
+       const char *product_name;
+       struct device *next_module;
+       /* The Rx and Tx rings are here to keep them quad-word-aligned. */
+       struct boom_rx_desc rx_ring[RX_RING_SIZE];
+       struct boom_tx_desc tx_ring[TX_RING_SIZE];
+       /* The addresses of transmit- and receive-in-place skbuffs. */
+       struct sk_buff* rx_skbuff[RX_RING_SIZE];
+       struct sk_buff* tx_skbuff[TX_RING_SIZE];
+       unsigned int cur_rx, cur_tx;            /* The next free ring entry */
+       unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
+       struct enet_statistics stats;
+       struct sk_buff *tx_skb;         /* Packet being eaten by bus master ctrl.  */
+       struct timer_list timer;        /* Media selection timer. */
+       int capabilities;                       /* Adapter capabilities word. */
+       int options;                            /* User-settable misc. driver options. */
+       int last_rx_packets;            /* For media autoselection. */
+       unsigned int available_media:8, /* From Wn3_Options */
+         media_override:3,                     /* Passed-in media type. */
+         default_media:3,                      /* Read from the EEPROM. */
+         full_duplex:1, autoselect:1,
+         bus_master:1,                         /* Vortex can only do a fragment bus-m. */
+         full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang  */
+      tx_full:1;
+};
+
+/* The action to take with a media selection timer tick.
+   Note that we deviate from the 3Com order by checking 10base2 before AUI.
+ */
+enum xcvr_types {
+       XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+       XCVR_100baseFx, XCVR_MII=6, XCVR_Default=8,
+};
+
+static struct media_table {
+  char *name;
+  unsigned int media_bits:16,          /* Bits to set in Wn4_Media register. */
+       mask:8,                         /* The transceiver-present bit in Wn3_Config.*/
+       next:8;                         /* The media type to try next. */
+  short wait;                  /* Time before we check media status. */
+} media_tbl[] = {
+  {    "10baseT",   Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
+  { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
+  { "undefined", 0,                    0x80, XCVR_10baseT, 10000},
+  { "10base2",   0,                    0x10, XCVR_AUI,         (1*HZ)/10},
+  { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
+  { "100baseFX", Media_Lnk, 0x04, XCVR_MII,            (14*HZ)/10},
+  { "MII",              0,                     0x40, XCVR_10baseT, 3*HZ },
+  { "undefined", 0,                    0x01, XCVR_10baseT, 10000},
+  { "Default",  0,                     0xFF, XCVR_10baseT, 10000},
+};
+
+static int vortex_scan(struct device *dev);
+static struct device *vortex_found_device(struct device *dev, int ioaddr,
+                                                                                 int irq, int product_index,
+                                                                                 int options);
+static int vortex_probe1(struct device *dev);
+static int vortex_open(struct device *dev);
+static void vortex_timer(unsigned long arg);
+static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
+static int vortex_rx(struct device *dev);
+static int boomerang_rx(struct device *dev);
+static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs);
+static int vortex_close(struct device *dev);
+static void update_stats(int addr, struct device *dev);
+static struct enet_statistics *vortex_get_stats(struct device *dev);
+static void set_rx_mode(struct device *dev);
+\f
+
+/* Unlike the other PCI cards the 59x cards don't need a large contiguous
+   memory region, so making the driver a loadable module is feasible.
+
+   Unfortunately maximizing the shared code between the integrated and
+   module version of the driver results in a complicated set of initialization
+   procedures.
+   init_module() -- modules /  tc59x_init()  -- built-in
+               The wrappers for vortex_scan()
+   vortex_scan()                The common routine that scans for PCI and EISA cards
+   vortex_found_device() Allocate a device structure when we find a card.
+                                       Different versions exist for modules and built-in.
+   vortex_probe1()             Fill in the device structure -- this is separated
+                                       so that the modules code can put it in dev->init.
+*/
+/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
+/* Note: this is the only limit on the number of cards supported!! */
+static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+
+#ifdef MODULE
+static int debug = -1;
+/* A list of all installed Vortex devices, for removing the driver module. */
+static struct device *root_vortex_dev = NULL;
+
+int
+init_module(void)
+{
+       int cards_found;
+
+       if (debug >= 0)
+               vortex_debug = debug;
+       if (vortex_debug)
+               printk(version);
+
+       root_vortex_dev = NULL;
+       cards_found = vortex_scan(0);
+       return cards_found ? 0 : -ENODEV;
+}
+
+#else
+int tc515_probe(struct device *dev)
+{
+       int cards_found = 0;
+
+       cards_found = vortex_scan(dev);
+
+       if (vortex_debug > 0  &&  cards_found)
+               printk(version);
+
+       return cards_found ? 0 : -ENODEV;
+}
+#endif  /* not MODULE */
+
+static int vortex_scan(struct device *dev)
+{
+       int cards_found = 0;
+       static int ioaddr = 0x100;
+
+       /* Check all locations on the ISA bus -- evil! */
+       for (; ioaddr < 0x400; ioaddr += 0x20) {
+         int irq;
+         if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
+               continue;
+         /* Check the resource configuration for a matching ioaddr. */
+         if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
+               continue;
+         /* Verify by reading the device ID from the EEPROM. */
+         {
+               int timer;
+               outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
+               /* Pause for at least 162 us. for the read to take place. */
+               for (timer = 4; timer >= 0; timer--) {
+                 udelay(162);
+                 if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+                       break;
+               }
+               if (inw(ioaddr + Wn0EepromData) != 0x6d50)
+                 continue;
+         }
+         printk("3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n",
+                        inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
+         irq = inw(ioaddr + 0x2002) & 15;
+         vortex_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev && dev->mem_start
+                                                 ? dev->mem_start : options[cards_found]);
+         dev = 0;
+         cards_found++;
+       }
+
+       if (vortex_debug)
+         printk("%d 3c515 cards found.\n", cards_found);
+       return cards_found;
+}
+
+static struct device *vortex_found_device(struct device *dev, int ioaddr,
+                                                                                 int irq, int product_index,
+                                                                                 int options)
+{
+       struct vortex_private *vp;
+
+#ifdef MODULE
+       /* Allocate and fill new device structure. */
+       int dev_size = sizeof(struct device) +
+               sizeof(struct vortex_private) + 15;             /* Pad for alignment */
+       
+       dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
+       memset(dev, 0, dev_size);
+       /* Align the Rx and Tx ring entries.  */
+       dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
+       vp = (struct vortex_private *)dev->priv;
+       dev->name = vp->devname; /* An empty string. */
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+       dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
+       dev->init = vortex_probe1;
+       vp->product_name = "3c515";
+       vp->options = options;
+       if (options >= 0) {
+               vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
+               vp->full_duplex = (options & 8) ? 1 : 0;
+               vp->bus_master = (options & 16) ? 1 : 0;
+       } else {
+               vp->media_override = 7;
+               vp->full_duplex = 0;
+               vp->bus_master = 0;
+       }
+       ether_setup(dev);
+       vp->next_module = root_vortex_dev;
+       root_vortex_dev = dev;
+       if (register_netdev(dev) != 0)
+               return 0;
+#else  /* not a MODULE */
+       if (dev) {
+               /* Caution: quad-word alignment required for rings! */
+               dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL);
+               memset(dev->priv, 0, sizeof (struct vortex_private));
+       }
+       dev = init_etherdev(dev, sizeof(struct vortex_private));
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+       dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
+       vp  = (struct vortex_private *)dev->priv;
+       vp->product_name = "3c515";
+       vp->options = options;
+       if (options >= 0) {
+               vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
+               vp->full_duplex = (options & 8) ? 1 : 0;
+               vp->bus_master = (options & 16) ? 1 : 0;
+       } else {
+               vp->media_override = 7;
+               vp->full_duplex = 0;
+               vp->bus_master = 0;
+       }
+
+       vortex_probe1(dev);
+#endif /* MODULE */
+       return dev;
+}
+
+static int vortex_probe1(struct device *dev)
+{
+       int ioaddr = dev->base_addr;
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       unsigned int eeprom[0x40], checksum = 0;                /* EEPROM contents */
+       int i;
+
+       printk("%s: 3Com %s at %#3x,", dev->name,
+                  vp->product_name, ioaddr);
+
+       /* Read the station address from the EEPROM. */
+       EL3WINDOW(0);
+       for (i = 0; i < 0x18; i++) {
+               short *phys_addr = (short *)dev->dev_addr;
+               int timer;
+               outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
+               /* Pause for at least 162 us. for the read to take place. */
+               for (timer = 4; timer >= 0; timer--) {
+                       udelay(162);
+                       if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+                               break;
+               }
+               eeprom[i] = inw(ioaddr + Wn0EepromData);
+               checksum ^= eeprom[i];
+               if (i < 3)
+                       phys_addr[i] = htons(eeprom[i]);
+       }
+       checksum = (checksum ^ (checksum >> 8)) & 0xff;
+       if (checksum != 0x00)
+               printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+       for (i = 0; i < 6; i++)
+               printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+       if (eeprom[16] == 0x11c7) {             /* Corkscrew */
+         if (request_dma(dev->dma, "3c515")) {
+               printk(", DMA %d allocation failed", dev->dma);
+               dev->dma = 0;
+         } else 
+               printk(", DMA %d", dev->dma);
+       }
+       printk(", IRQ %d\n", dev->irq);
+       /* Tell them about an invalid IRQ. */
+       if (vortex_debug && (dev->irq <= 0 || dev->irq > 15))
+               printk(" *** Warning: this IRQ is unlikely to work! ***\n");
+
+       {
+               char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+               union wn3_config config;
+               EL3WINDOW(3);
+               vp->available_media = inw(ioaddr + Wn3_Options);
+               config.i = inl(ioaddr + Wn3_Config);
+               if (vortex_debug > 1)
+                       printk("  Internal config register is %4.4x, transceivers %#x.\n",
+                                  config.i, inw(ioaddr + Wn3_Options));
+               printk("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+                          8 << config.u.ram_size,
+                          config.u.ram_width ? "word" : "byte",
+                          ram_split[config.u.ram_split],
+                          config.u.autoselect ? "autoselect/" : "",
+                          media_tbl[config.u.xcvr].name);
+               dev->if_port = config.u.xcvr;
+               vp->default_media = config.u.xcvr;
+               vp->autoselect = config.u.autoselect;
+       }
+       if (vp->media_override != 7) {
+               printk("  Media override to transceiver type %d (%s).\n",
+                          vp->media_override, media_tbl[vp->media_override].name);
+               dev->if_port = vp->media_override;
+       }
+
+       vp->capabilities = eeprom[16];
+       vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
+       /* Rx is broken at 10mbps, so we always disable it. */
+       /* vp->full_bus_master_rx = 0;*/
+       vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
+
+       /* We do a request_region() to register /proc/ioports info. */
+       request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name);
+
+       /* The 3c59x-specific entries in the device structure. */
+       dev->open = &vortex_open;
+       dev->hard_start_xmit = &vortex_start_xmit;
+       dev->stop = &vortex_close;
+       dev->get_stats = &vortex_get_stats;
+       dev->set_multicast_list = &set_rx_mode;
+
+       return 0;
+}
+
+\f
+static int
+vortex_open(struct device *dev)
+{
+       int ioaddr = dev->base_addr;
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       union wn3_config config;
+       int i;
+
+       /* Before initializing select the active media port. */
+       EL3WINDOW(3);
+       if (vp->full_duplex)
+               outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
+       config.i = inl(ioaddr + Wn3_Config);
+
+       if (vp->media_override != 7) {
+               if (vortex_debug > 1)
+                       printk("%s: Media override to transceiver %d (%s).\n",
+                                  dev->name, vp->media_override,
+                                  media_tbl[vp->media_override].name);
+               dev->if_port = vp->media_override;
+       } else if (vp->autoselect) {
+               /* Find first available media type, starting with 100baseTx. */
+               dev->if_port = 4;
+               while (! (vp->available_media & media_tbl[dev->if_port].mask))
+                       dev->if_port = media_tbl[dev->if_port].next;
+
+               if (vortex_debug > 1)
+                       printk("%s: Initial media type %s.\n",
+                                  dev->name, media_tbl[dev->if_port].name);
+
+               init_timer(&vp->timer);
+               vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+               vp->timer.data = (unsigned long)dev;
+               vp->timer.function = &vortex_timer;    /* timer handler */
+               add_timer(&vp->timer);
+       } else
+               dev->if_port = vp->default_media;
+
+       config.u.xcvr = dev->if_port;
+       outl(config.i, ioaddr + Wn3_Config);
+
+       if (vortex_debug > 1) {
+               printk("%s: vortex_open() InternalConfig %8.8x.\n",
+                       dev->name, config.i);
+       }
+
+       outw(TxReset, ioaddr + EL3_CMD);
+       for (i = 20; i >= 0 ; i--)
+               if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+                       break;
+
+       outw(RxReset, ioaddr + EL3_CMD);
+       /* Wait a few ticks for the RxReset command to complete. */
+       for (i = 20; i >= 0 ; i--)
+               if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+                       break;
+
+       outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+
+       /* Use the now-standard shared IRQ implementation. */
+       if (vp->capabilities == 0x11c7) {
+         /* Corkscrew: Cannot share ISA resources. */
+         if (dev->irq == 0
+                 || dev->dma == 0
+                 || request_irq(dev->irq, &vortex_interrupt, 0,
+                                                vp->product_name, dev))
+               return -EAGAIN;
+         enable_dma(dev->dma);
+         set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+       } else if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ,
+                                                  vp->product_name, dev)) {
+         return -EAGAIN;
+       }
+
+       if (vortex_debug > 1) {
+               EL3WINDOW(4);
+               printk("%s: vortex_open() irq %d media status %4.4x.\n",
+                          dev->name, dev->irq, inw(ioaddr + Wn4_Media));
+       }
+
+       /* Set the station address and mask in window 2 each time opened. */
+       EL3WINDOW(2);
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + i);
+       for (; i < 12; i+=2)
+               outw(0, ioaddr + i);
+
+       if (dev->if_port == 3)
+               /* Start the thinnet transceiver. We should really wait 50ms...*/
+               outw(StartCoax, ioaddr + EL3_CMD);
+       EL3WINDOW(4);
+       outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+                media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+
+       /* Switch to the stats window, and clear all stats by reading. */
+       outw(StatsDisable, ioaddr + EL3_CMD);
+       EL3WINDOW(6);
+       for (i = 0; i < 10; i++)        
+               inb(ioaddr + i);
+       inw(ioaddr + 10);
+       inw(ioaddr + 12);
+       /* New: On the Vortex we must also clear the BadSSD counter. */
+       EL3WINDOW(4);
+       inb(ioaddr + 12);
+       /* ..and on the Boomerang we enable the extra statistics bits. */
+       outw(0x0040, ioaddr + Wn4_NetDiag);
+
+       /* Switch to register set 7 for normal use. */
+       EL3WINDOW(7);
+
+       if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+               vp->cur_rx = vp->dirty_rx = 0;
+               if (vortex_debug > 2)
+                       printk("%s:  Filling in the Rx ring.\n", dev->name);
+               for (i = 0; i < RX_RING_SIZE; i++) {
+                       struct sk_buff *skb;
+                       if (i < (RX_RING_SIZE - 1))
+                         vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]);
+                       else
+                         vp->rx_ring[i].next = 0;
+                       vp->rx_ring[i].status = 0;      /* Clear complete bit. */
+                       vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
+                       skb = dev_alloc_skb(PKT_BUF_SZ);
+                       vp->rx_skbuff[i] = skb;
+                       if (skb == NULL)
+                               break;                  /* Bad news!  */
+                       skb->dev = dev;                 /* Mark as being used by this device. */
+                       skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+                       vp->rx_ring[i].addr = virt_to_bus(skb->tail);
+               }
+               vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
+               outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+       }
+       if (vp->full_bus_master_tx) {           /* Boomerang bus master Tx. */
+               vp->cur_tx = vp->dirty_tx = 0;
+               outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+               /* Clear the Tx ring. */
+               for (i = 0; i < TX_RING_SIZE; i++)
+                       vp->tx_skbuff[i] = 0;
+               outl(0, ioaddr + DownListPtr);
+       }
+       /* Set reciever mode: presumably accept b-case and phys addr only. */
+       set_rx_mode(dev);
+       outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+
+       dev->tbusy = 0;
+       dev->interrupt = 0;
+       dev->start = 1;
+
+       outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+       outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+       /* Allow status bits to be seen. */
+       outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull | 
+                (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+                (vp->full_bus_master_rx ? UpComplete : RxComplete) | 
+                (vp->bus_master ? DMADone : 0),
+                ioaddr + EL3_CMD);
+       /* Ack all pending events, and set active indicator mask. */
+       outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+                ioaddr + EL3_CMD);
+       outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+                | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
+                       ioaddr + EL3_CMD);
+
+       MOD_INC_USE_COUNT;
+
+       return 0;
+}
+
+static void vortex_timer(unsigned long data)
+{
+#ifdef AUTOMEDIA
+       struct device *dev = (struct device *)data;
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+       unsigned long flags;
+       int ok = 0;
+
+       if (vortex_debug > 1)
+               printk("%s: Media selection timer tick happened, %s.\n",
+                          dev->name, media_tbl[dev->if_port].name);
+
+       save_flags(flags);      cli(); {
+         int old_window = inw(ioaddr + EL3_CMD) >> 13;
+         int media_status;
+         EL3WINDOW(4);
+         media_status = inw(ioaddr + Wn4_Media);
+         switch (dev->if_port) {
+         case 0:  case 4:  case 5:             /* 10baseT, 100baseTX, 100baseFX  */
+               if (media_status & Media_LnkBeat) {
+                 ok = 1;
+                 if (vortex_debug > 1)
+                       printk("%s: Media %s has link beat, %x.\n",
+                                  dev->name, media_tbl[dev->if_port].name, media_status);
+               } else if (vortex_debug > 1)
+                 printk("%s: Media %s is has no link beat, %x.\n",
+                                  dev->name, media_tbl[dev->if_port].name, media_status);
+               break;
+         default:                                      /* Other media types handled by Tx timeouts. */
+               if (vortex_debug > 1)
+                 printk("%s: Media %s is has no indication, %x.\n",
+                                dev->name, media_tbl[dev->if_port].name, media_status);
+               ok = 1;
+         }
+         if ( ! ok) {
+               union wn3_config config;
+
+               do {
+                       dev->if_port = media_tbl[dev->if_port].next;
+               } while ( ! (vp->available_media & media_tbl[dev->if_port].mask));
+               if (dev->if_port == 8) { /* Go back to default. */
+                 dev->if_port = vp->default_media;
+                 if (vortex_debug > 1)
+                       printk("%s: Media selection failing, using default %s port.\n",
+                                  dev->name, media_tbl[dev->if_port].name);
+               } else {
+                 if (vortex_debug > 1)
+                       printk("%s: Media selection failed, now trying %s port.\n",
+                                  dev->name, media_tbl[dev->if_port].name);
+                 vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+                 add_timer(&vp->timer);
+               }
+               outw((media_status & ~(Media_10TP|Media_SQE)) |
+                        media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+
+               EL3WINDOW(3);
+               config.i = inl(ioaddr + Wn3_Config);
+               config.u.xcvr = dev->if_port;
+               outl(config.i, ioaddr + Wn3_Config);
+
+               outw(dev->if_port == 3 ? StartCoax : StopCoax, ioaddr + EL3_CMD);
+         }
+         EL3WINDOW(old_window);
+       }   restore_flags(flags);
+       if (vortex_debug > 1)
+         printk("%s: Media selection timer finished, %s.\n",
+                        dev->name, media_tbl[dev->if_port].name);
+
+#endif /* AUTOMEDIA*/
+       return;
+}
+
+static int
+vortex_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+
+       if (dev->tbusy) {
+               int tickssofar = jiffies - dev->trans_start;
+               int i;
+
+               /* Min. wait before assuming a Tx failed == 400ms. */
+
+               if (tickssofar < 400*HZ/1000)           /* We probably aren't empty. */
+                       return 1;
+               printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+                          dev->name, inb(ioaddr + TxStatus),
+                          inw(ioaddr + EL3_STATUS));
+               /* Slight code bloat to be user friendly. */
+               if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
+                       printk("%s: Transmitter encountered 16 collisions -- network"
+                                  " network cable problem?\n", dev->name);
+#ifndef final_version
+               printk("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
+                          vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
+               printk("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
+                          &vp->tx_ring[0]);
+               for (i = 0; i < TX_RING_SIZE; i++) {
+                       printk("  %d: %p  length %8.8x status %8.8x\n", i,
+                                  &vp->tx_ring[i],
+                                  vp->tx_ring[i].length,
+                                  vp->tx_ring[i].status);
+               }
+#endif
+               /* Issue TX_RESET and TX_START commands. */
+               outw(TxReset, ioaddr + EL3_CMD);
+               for (i = 20; i >= 0 ; i--)
+                       if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+                               break;
+               outw(TxEnable, ioaddr + EL3_CMD);
+               dev->trans_start = jiffies;
+               /* dev->tbusy = 0;*/
+               vp->stats.tx_errors++;
+               vp->stats.tx_dropped++;
+               return 0;                       /* Yes, silently *drop* the packet! */
+       }
+
+       /* Block a timer-based transmit from overlapping.  This could better be
+          done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+          If this ever occurs the queue layer is doing something evil! */
+       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+               printk("%s: Transmitter access conflict.\n", dev->name);
+               return 1;
+       }
+
+       if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */
+               /* Calculate the next Tx descriptor entry. */
+               int entry = vp->cur_tx % TX_RING_SIZE;
+               struct boom_tx_desc *prev_entry;
+               unsigned long flags, i;
+
+               if (vp->tx_full) /* No room to transmit with */
+                 return 1;
+               if (vp->cur_tx != 0)
+                 prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
+               else
+                 prev_entry = NULL;
+               if (vortex_debug > 3)
+                       printk("%s: Trying to send a packet, Tx index %d.\n",
+                                  dev->name, vp->cur_tx);
+               /* vp->tx_full = 1; */
+               vp->tx_skbuff[entry] = skb;
+               vp->tx_ring[entry].next = 0;
+               vp->tx_ring[entry].addr = virt_to_bus(skb->data);
+               vp->tx_ring[entry].length = skb->len | 0x80000000;
+               vp->tx_ring[entry].status = skb->len | 0x80000000;
+
+               save_flags(flags);
+               cli();
+               outw(DownStall, ioaddr + EL3_CMD);
+               /* Wait for the stall to complete. */
+               for (i = 20; i >= 0 ; i--)
+                       if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
+                               break;
+               if (prev_entry)
+                 prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
+               if (inl(ioaddr + DownListPtr) == 0) {
+                       outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
+                       queued_packet++;
+               }
+               outw(DownUnstall, ioaddr + EL3_CMD);
+               restore_flags(flags);
+
+               vp->cur_tx++;
+               if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+                       vp->tx_full = 1;
+               else {                                  /* Clear previous interrupt enable. */
+                 if (prev_entry)
+                       prev_entry->status &= ~0x80000000;
+                 dev->tbusy = 0;
+               }
+               dev->trans_start = jiffies;
+               return 0;
+       }
+       /* Put out the doubleword header... */
+       outl(skb->len, ioaddr + TX_FIFO);
+#ifdef VORTEX_BUS_MASTER
+       if (vp->bus_master) {
+               /* Set the bus-master controller to transfer the packet. */
+               outl((int)(skb->data), ioaddr + Wn7_MasterAddr);
+               outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+               vp->tx_skb = skb;
+               outw(StartDMADown, ioaddr + EL3_CMD);
+               /* dev->tbusy will be cleared at the DMADone interrupt. */
+       } else {
+               /* ... and the packet rounded to a doubleword. */
+               outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+               dev_kfree_skb (skb);
+               if (inw(ioaddr + TxFree) > 1536) {
+                       dev->tbusy = 0;
+               } else
+                       /* Interrupt us when the FIFO has room for max-sized packet. */
+                       outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+       }
+#else
+       /* ... and the packet rounded to a doubleword. */
+       outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+       dev_kfree_skb (skb);
+       if (inw(ioaddr + TxFree) > 1536) {
+               dev->tbusy = 0;
+       } else
+               /* Interrupt us when the FIFO has room for max-sized packet. */
+               outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+#endif  /* bus master */
+
+       dev->trans_start = jiffies;
+
+       /* Clear the Tx status stack. */
+       {
+               short tx_status;
+               int i = 4;
+
+               while (--i > 0  &&      (tx_status = inb(ioaddr + TxStatus)) > 0) {
+                       if (tx_status & 0x3C) {         /* A Tx-disabling error occurred.  */
+                               if (vortex_debug > 2)
+                                 printk("%s: Tx error, status %2.2x.\n",
+                                                dev->name, tx_status);
+                               if (tx_status & 0x04) vp->stats.tx_fifo_errors++;
+                               if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
+                               if (tx_status & 0x30) {
+                                       int j;
+                                       outw(TxReset, ioaddr + EL3_CMD);
+                                       for (j = 20; j >= 0 ; j--)
+                                               if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+                                                       break;
+                               }
+                               outw(TxEnable, ioaddr + EL3_CMD);
+                       }
+                       outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+               }
+       }
+       return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /* Use the now-standard shared IRQ implementation. */
+       struct device *dev = dev_id;
+       struct vortex_private *lp;
+       int ioaddr, status;
+       int latency;
+       int i = max_interrupt_work;
+
+       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+               printk("%s: Re-entering the interrupt handler.\n", dev->name);
+               return;
+       }
+
+       ioaddr = dev->base_addr;
+       latency = inb(ioaddr + Timer);
+       lp = (struct vortex_private *)dev->priv;
+
+       status = inw(ioaddr + EL3_STATUS);
+
+       if (vortex_debug > 4)
+               printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name,
+                          status, latency);
+       if ((status & 0xE000) != 0xE000) {
+               static int donedidthis=0;
+               /* Some interrupt controllers store a bogus interrupt from boot-time.
+                  Ignore a single early interrupt, but don't hang the machine for
+                  other interrupt problems. */
+               if (donedidthis++ > 100) {
+                       printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
+                                  dev->name, status, dev->start);
+                       FREE_IRQ(dev->irq, dev);
+               }
+       }
+
+       do {
+               if (vortex_debug > 5)
+                               printk("%s: In interrupt loop, status %4.4x.\n",
+                                          dev->name, status);
+               if (status & RxComplete)
+                       vortex_rx(dev);
+
+               if (status & TxAvailable) {
+                       if (vortex_debug > 5)
+                               printk("        TX room bit was handled.\n");
+                       /* There's room in the FIFO for a full-sized packet. */
+                       outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+                       dev->tbusy = 0;
+                       mark_bh(NET_BH);
+               }
+               if (status & DownComplete) {
+                       unsigned int dirty_tx = lp->dirty_tx;
+
+                       while (lp->cur_tx - dirty_tx > 0) {
+                               int entry = dirty_tx % TX_RING_SIZE;
+                               if (inl(ioaddr + DownListPtr) ==
+                                       virt_to_bus(&lp->tx_ring[entry]))
+                                       break;                  /* It still hasn't been processed. */
+                               if (lp->tx_skbuff[entry]) {
+                                       dev_kfree_skb(lp->tx_skbuff[entry]);
+                                       lp->tx_skbuff[entry] = 0;
+                               }
+                               dirty_tx++;
+                       }
+                       lp->dirty_tx = dirty_tx;
+                       outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
+                       if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
+                               lp->tx_full= 0;
+                               dev->tbusy = 0;
+                               mark_bh(NET_BH);
+                       }
+               }
+#ifdef VORTEX_BUS_MASTER
+               if (status & DMADone) {
+                       outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+                       dev->tbusy = 0;
+                       dev_kfree_skb (lp->tx_skb); /* Release the transfered buffer */
+                       mark_bh(NET_BH);
+               }
+#endif
+               if (status & UpComplete) {
+                       boomerang_rx(dev);
+                       outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
+               }
+               if (status & (AdapterFailure | RxEarly | StatsFull)) {
+                       /* Handle all uncommon interrupts at once. */
+                       if (status & RxEarly) {                         /* Rx early is unused. */
+                               vortex_rx(dev);
+                               outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+                       }
+                       if (status & StatsFull) {       /* Empty statistics. */
+                               static int DoneDidThat = 0;
+                               if (vortex_debug > 4)
+                                       printk("%s: Updating stats.\n", dev->name);
+                               update_stats(ioaddr, dev);
+                               /* DEBUG HACK: Disable statistics as an interrupt source. */
+                               /* This occurs when we have the wrong media type! */
+                               if (DoneDidThat == 0  &&
+                                       inw(ioaddr + EL3_STATUS) & StatsFull) {
+                                       int win, reg;
+                                       printk("%s: Updating stats failed, disabling stats as an"
+                                                  " interrupt source.\n", dev->name);
+                                       for (win = 0; win < 8; win++) {
+                                               EL3WINDOW(win);
+                                               printk("\n Vortex window %d:", win);
+                                               for (reg = 0; reg < 16; reg++)
+                                                       printk(" %2.2x", inb(ioaddr+reg));
+                                       }
+                                       EL3WINDOW(7);
+                                       outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure
+                                                | UpComplete | DownComplete | TxComplete,
+                                                ioaddr + EL3_CMD);
+                                       DoneDidThat++;
+                               }
+                       }
+                       if (status & AdapterFailure) {
+                               /* Adapter failure requires Rx reset and reinit. */
+                               outw(RxReset, ioaddr + EL3_CMD);
+                               /* Set the Rx filter to the current state. */
+                               set_rx_mode(dev);
+                               outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+                               outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+                       }
+               }
+
+               if (--i < 0) {
+                       printk("%s: Too much work in interrupt, status %4.4x.  "
+                                  "Disabling functions (%4.4x).\n",
+                                  dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
+                       /* Disable all pending interrupts. */
+                       outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
+                       outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
+                       break;
+               }
+               /* Acknowledge the IRQ. */
+               outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+
+       } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+
+       if (vortex_debug > 4)
+               printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
+
+       dev->interrupt = 0;
+       return;
+}
+
+static int
+vortex_rx(struct device *dev)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+       int i;
+       short rx_status;
+
+       if (vortex_debug > 5)
+               printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+                          inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+       while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
+               if (rx_status & 0x4000) { /* Error, update stats. */
+                       unsigned char rx_error = inb(ioaddr + RxErrors);
+                       if (vortex_debug > 2)
+                               printk(" Rx error: status %2.2x.\n", rx_error);
+                       vp->stats.rx_errors++;
+                       if (rx_error & 0x01)  vp->stats.rx_over_errors++;
+                       if (rx_error & 0x02)  vp->stats.rx_length_errors++;
+                       if (rx_error & 0x04)  vp->stats.rx_frame_errors++;
+                       if (rx_error & 0x08)  vp->stats.rx_crc_errors++;
+                       if (rx_error & 0x10)  vp->stats.rx_length_errors++;
+               } else {
+                       /* The packet length: up to 4.5K!. */
+                       short pkt_len = rx_status & 0x1fff;
+                       struct sk_buff *skb;
+
+                       skb = DEV_ALLOC_SKB(pkt_len + 5);
+                       if (vortex_debug > 4)
+                               printk("Receiving packet size %d status %4.4x.\n",
+                                          pkt_len, rx_status);
+                       if (skb != NULL) {
+                               skb->dev = dev;
+#if LINUX_VERSION_CODE >= 0x10300
+                               skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+                               /* 'skb_put()' points to the start of sk_buff data area. */
+                               insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
+                                        (pkt_len + 3) >> 2);
+                               outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+                               skb->protocol = eth_type_trans(skb, dev);
+#else
+                               skb->len = pkt_len;
+                               /* 'skb->data' points to the start of sk_buff data area. */
+                               insl(ioaddr + RX_FIFO, skb->data, (pkt_len + 3) >> 2);
+                               outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+#endif  /* KERNEL_1_3_0 */
+                               netif_rx(skb);
+                               dev->last_rx = jiffies;
+                               vp->stats.rx_packets++;
+                               /* Wait a limited time to go to next packet. */
+                               for (i = 200; i >= 0; i--)
+                                       if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+                                               break;
+                               continue;
+                       } else if (vortex_debug)
+                               printk("%s: Couldn't allocate a sk_buff of size %d.\n",
+                                          dev->name, pkt_len);
+               }
+               outw(RxDiscard, ioaddr + EL3_CMD);
+               vp->stats.rx_dropped++;
+               /* Wait a limited time to skip this packet. */
+               for (i = 200; i >= 0; i--)
+                       if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+                               break;
+       }
+
+       return 0;
+}
+
+static int
+boomerang_rx(struct device *dev)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       int entry = vp->cur_rx % RX_RING_SIZE;
+       int ioaddr = dev->base_addr;
+       int rx_status;
+
+       if (vortex_debug > 5)
+               printk("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
+                          inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+       while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
+               if (rx_status & RxDError) { /* Error, update stats. */
+                       unsigned char rx_error = rx_status >> 16;
+                       if (vortex_debug > 2)
+                               printk(" Rx error: status %2.2x.\n", rx_error);
+                       vp->stats.rx_errors++;
+                       if (rx_error & 0x01)  vp->stats.rx_over_errors++;
+                       if (rx_error & 0x02)  vp->stats.rx_length_errors++;
+                       if (rx_error & 0x04)  vp->stats.rx_frame_errors++;
+                       if (rx_error & 0x08)  vp->stats.rx_crc_errors++;
+                       if (rx_error & 0x10)  vp->stats.rx_length_errors++;
+               } else {
+                       /* The packet length: up to 4.5K!. */
+                       short pkt_len = rx_status & 0x1fff;
+                       struct sk_buff *skb;
+
+                       if (vortex_debug > 4)
+                               printk("Receiving packet size %d status %4.4x.\n",
+                                          pkt_len, rx_status);
+
+                       /* Check if the packet is long enough to just accept without
+                          copying to a properly sized skbuff. */
+                       if (pkt_len < rx_copybreak
+                               && (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) {
+                               skb->dev = dev;
+                               skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+                               /* 'skb_put()' points to the start of sk_buff data area. */
+                               memcpy(skb_put(skb, pkt_len),
+                                          bus_to_virt(vp->rx_ring[entry].addr),
+                                          pkt_len);
+                               rx_copy++;
+                       } else{
+                               void *temp;
+                               /* Pass up the skbuff already on the Rx ring. */
+                               skb = vp->rx_skbuff[entry];
+                               vp->rx_skbuff[entry] = NULL;
+                               temp = skb_put(skb, pkt_len);
+                               /* Remove this checking code for final release. */
+                               if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
+                                       printk("%s: Warning -- the skbuff addresses do not match"
+                                                  " in boomerang_rx: %p vs. %p / %p.\n", dev->name,
+                                                  bus_to_virt(vp->rx_ring[entry].addr),
+                                                  skb->head, temp);
+                               rx_nocopy++;
+                       }
+#if LINUX_VERSION_CODE > 0x10300
+                       skb->protocol = eth_type_trans(skb, dev);
+#else
+                       skb->len = pkt_len;
+#endif
+                       netif_rx(skb);
+                       dev->last_rx = jiffies;
+                       vp->stats.rx_packets++;
+               }
+               entry = (++vp->cur_rx) % RX_RING_SIZE;
+       }
+       /* Refill the Rx ring buffers. */
+       for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) {
+               struct sk_buff *skb;
+               entry = vp->dirty_rx % RX_RING_SIZE;
+               if (vp->rx_skbuff[entry] == NULL) {
+                       skb = dev_alloc_skb(PKT_BUF_SZ);
+                       if (skb == NULL)
+                               break;                  /* Bad news!  */
+                       skb->dev = dev;                 /* Mark as being used by this device. */
+#if LINUX_VERSION_CODE > 0x10300
+                       skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+                       vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
+#else
+                       vp->rx_ring[entry].addr = virt_to_bus(skb->data);
+#endif
+                       vp->rx_skbuff[entry] = skb;
+               }
+               vp->rx_ring[entry].status = 0;  /* Clear complete bit. */
+       }
+       return 0;
+}
+
+static int
+vortex_close(struct device *dev)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+       int i;
+
+       dev->start = 0;
+       dev->tbusy = 1;
+
+       if (vortex_debug > 1) {
+               printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
+                          dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
+               printk("%s: vortex close stats: rx_nocopy %d rx_copy %d"
+                          " tx_queued %d.\n",
+                          dev->name, rx_nocopy, rx_copy, queued_packet);
+       }
+
+       del_timer(&vp->timer);
+
+       /* Turn off statistics ASAP.  We update lp->stats below. */
+       outw(StatsDisable, ioaddr + EL3_CMD);
+
+       /* Disable the receiver and transmitter. */
+       outw(RxDisable, ioaddr + EL3_CMD);
+       outw(TxDisable, ioaddr + EL3_CMD);
+
+       if (dev->if_port == XCVR_10base2)
+               /* Turn off thinnet power.  Green! */
+               outw(StopCoax, ioaddr + EL3_CMD);
+
+#ifdef SA_SHIRQ
+       free_irq(dev->irq, dev);
+#else
+       free_irq(dev->irq);
+       irq2dev_map[dev->irq] = 0;
+#endif
+
+       outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+
+       update_stats(ioaddr, dev);
+       if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
+               outl(0, ioaddr + UpListPtr);
+               for (i = 0; i < RX_RING_SIZE; i++)
+                       if (vp->rx_skbuff[i]) {
+#if LINUX_VERSION_CODE < 0x20100
+                               vp->rx_skbuff[i]->free = 1;
+#endif
+                               dev_kfree_skb (vp->rx_skbuff[i]);
+                               vp->rx_skbuff[i] = 0;
+                       }
+       }
+       if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
+               outl(0, ioaddr + DownListPtr);
+               for (i = 0; i < TX_RING_SIZE; i++)
+                       if (vp->tx_skbuff[i]) {
+                               dev_kfree_skb(vp->tx_skbuff[i]);
+                               vp->tx_skbuff[i] = 0;
+                       }
+       }
+
+       MOD_DEC_USE_COUNT;
+
+       return 0;
+}
+
+static struct enet_statistics *
+vortex_get_stats(struct device *dev)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       unsigned long flags;
+
+       if (dev->start) {
+               save_flags(flags);
+               cli();
+               update_stats(dev->base_addr, dev);
+               restore_flags(flags);
+       }
+       return &vp->stats;
+}
+
+/*  Update statistics.
+       Unlike with the EL3 we need not worry about interrupts changing
+       the window setting from underneath us, but we must still guard
+       against a race condition with a StatsUpdate interrupt updating the
+       table.  This is done by checking that the ASM (!) code generated uses
+       atomic updates with '+='.
+       */
+static void update_stats(int ioaddr, struct device *dev)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+
+       /* Unlike the 3c5x9 we need not turn off stats updates while reading. */
+       /* Switch to the stats window, and read everything. */
+       EL3WINDOW(6);
+       vp->stats.tx_carrier_errors             += inb(ioaddr + 0);
+       vp->stats.tx_heartbeat_errors   += inb(ioaddr + 1);
+       /* Multiple collisions. */              inb(ioaddr + 2);
+       vp->stats.collisions                    += inb(ioaddr + 3);
+       vp->stats.tx_window_errors              += inb(ioaddr + 4);
+       vp->stats.rx_fifo_errors                += inb(ioaddr + 5);
+       vp->stats.tx_packets                    += inb(ioaddr + 6);
+       vp->stats.tx_packets                    += (inb(ioaddr + 9)&0x30) << 4;
+       /* Rx packets   */                              inb(ioaddr + 7);   /* Must read to clear */
+       /* Tx deferrals */                              inb(ioaddr + 8);
+       /* Don't bother with register 9, an extension of registers 6&7.
+          If we do use the 6&7 values the atomic update assumption above
+          is invalid. */
+       inw(ioaddr + 10);       /* Total Rx and Tx octets. */
+       inw(ioaddr + 12);
+       /* New: On the Vortex we must also clear the BadSSD counter. */
+       EL3WINDOW(4);
+       inb(ioaddr + 12);
+
+       /* We change back to window 7 (not 1) with the Vortex. */
+       EL3WINDOW(7);
+       return;
+}
+
+/* This new version of set_rx_mode() supports v1.4 kernels.
+   The Vortex chip has no documented multicast filter, so the only
+   multicast setting is to receive all multicast frames.  At least
+   the chip has a very clean way to set the mode, unlike many others. */
+static void
+set_rx_mode(struct device *dev)
+{
+       int ioaddr = dev->base_addr;
+       short new_mode;
+
+       if (dev->flags & IFF_PROMISC) {
+               if (vortex_debug > 3)
+                       printk("%s: Setting promiscuous mode.\n", dev->name);
+               new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
+       } else  if ((dev->mc_list)  ||  (dev->flags & IFF_ALLMULTI)) {
+               new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
+       } else
+               new_mode = SetRxFilter | RxStation | RxBroadcast;
+
+       outw(new_mode, ioaddr + EL3_CMD);
+}
+\f
+#ifdef MODULE
+void
+cleanup_module(void)
+{
+       struct device *next_dev;
+
+       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+       while (root_vortex_dev) {
+               next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
+               if (root_vortex_dev->dma)
+                 free_dma(root_vortex_dev->dma);
+               unregister_netdev(root_vortex_dev);
+               outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
+               release_region(root_vortex_dev->base_addr, CORKSCREW_TOTAL_SIZE);
+               kfree(root_vortex_dev);
+               root_vortex_dev = next_dev;
+       }
+}
+#endif /* MODULE */
+\f
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c515.c"
+ *  c-indent-level: 4
+ *  tab-width: 4
+ * End:
+ */
index 10c4553a9a6a697aecd7e2d93e5c5c6ad2dd303f..968168d012aad0a8eb981e16be1a12d57eb56917 100644 (file)
@@ -1,84 +1,84 @@
 /*
-net-3-driver for the 3c523 Etherlink/MC card (i82586 Ethernet chip)
+   net-3-driver for the 3c523 Etherlink/MC card (i82586 Ethernet chip)
 
 
-This is an extension to the Linux operating system, and is covered by the
-same Gnu Public License that covers that work.
+   This is an extension to the Linux operating system, and is covered by the
+   same Gnu Public License that covers that work.
 
-Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
+   Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
 
-This is basically Michael Hipp's ni52 driver, with a new probing
-algorithm and some minor changes to the 82586 CA and reset routines.
-Thanks a lot Michael for a really clean i82586 implementation!  Unless
-otherwise documented in ni52.c, any bugs are mine.
+   This is basically Michael Hipp's ni52 driver, with a new probing
+   algorithm and some minor changes to the 82586 CA and reset routines.
+   Thanks a lot Michael for a really clean i82586 implementation!  Unless
+   otherwise documented in ni52.c, any bugs are mine.
 
-Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in
-any way.  The ni52 is a lot easier to modify.
+   Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in
+   any way.  The ni52 is a lot easier to modify.
 
-sources:
-  ni52.c
+   sources:
+   ni52.c
 
-  Crynwr packet driver collection was a great reference for my first
-  attempt at this sucker.  The 3c507 driver also helped, until I noticed
-  that ni52.c was a lot nicer.
+   Crynwr packet driver collection was a great reference for my first
+   attempt at this sucker.  The 3c507 driver also helped, until I noticed
+   that ni52.c was a lot nicer.
 
-  EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference
-  Manual, courtesy of 3Com CardFacts, documents the 3c523-specific
-  stuff.  Information on CardFacts is found in the Ethernet HOWTO.
-  Also see <a href="http://www.3com.com/">
+   EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference
+   Manual, courtesy of 3Com CardFacts, documents the 3c523-specific
+   stuff.  Information on CardFacts is found in the Ethernet HOWTO.
+   Also see <a href="http://www.3com.com/">
 
-  Microprocessor Communications Support Chips, T.J. Byers, ISBN
-  0-444-01224-9, has a section on the i82586.  It tells you just enough
-  to know that you really don't want to learn how to program the chip.
+   Microprocessor Communications Support Chips, T.J. Byers, ISBN
+   0-444-01224-9, has a section on the i82586.  It tells you just enough
+   to know that you really don't want to learn how to program the chip.
 
-  The original device probe code was stolen from ps2esdi.c
+   The original device probe code was stolen from ps2esdi.c
 
-Known Problems:
-  Since most of the code was stolen from ni52.c, you'll run across the
-  same bugs in the 0.62 version of ni52.c, plus maybe a few because of
-  the 3c523 idiosynchacies.  The 3c523 has 16K of RAM though, so there
-  shouldn't be the overrun problem that the 8K ni52 has.
+   Known Problems:
+   Since most of the code was stolen from ni52.c, you'll run across the
+   same bugs in the 0.62 version of ni52.c, plus maybe a few because of
+   the 3c523 idiosynchacies.  The 3c523 has 16K of RAM though, so there
+   shouldn't be the overrun problem that the 8K ni52 has.
 
-  This driver is for a 16K adapter.  It should work fine on the 64K
-  adapters, but it will only use one of the 4 banks of RAM.  Modifying
-  this for the 64K version would require a lot of heinous bank
-  switching, which I'm sure not interested in doing.  If you try to
-  implement a bank switching version, you'll basically have to remember
-  what bank is enabled and do a switch everytime you access a memory
-  location that's not current.  You'll also have to remap pointers on
-  the driver side, because it only knows about 16K of the memory.
-  Anyone desperate or masochistic enough to try?
+   This driver is for a 16K adapter.  It should work fine on the 64K
+   adapters, but it will only use one of the 4 banks of RAM.  Modifying
+   this for the 64K version would require a lot of heinous bank
+   switching, which I'm sure not interested in doing.  If you try to
+   implement a bank switching version, you'll basically have to remember
+   what bank is enabled and do a switch everytime you access a memory
+   location that's not current.  You'll also have to remap pointers on
+   the driver side, because it only knows about 16K of the memory.
+   Anyone desperate or masochistic enough to try?
 
-  It seems to be stable now when multiple transmit buffers are used.  I
-  can't see any performance difference, but then I'm working on a 386SX.
+   It seems to be stable now when multiple transmit buffers are used.  I
+   can't see any performance difference, but then I'm working on a 386SX.
 
-  Multicast doesn't work.  It doesn't even pretend to work.  Don't use
-  it.  Don't compile your kernel with multicast support.  I don't know
-  why.
+   Multicast doesn't work.  It doesn't even pretend to work.  Don't use
+   it.  Don't compile your kernel with multicast support.  I don't know
+   why.
 
-Features:
-  This driver is useable as a loadable module.  If you try to specify an
-  IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will
-  search the MCA slots until it finds a 3c523 with the specified
-  parameters.
+   Features:
+   This driver is useable as a loadable module.  If you try to specify an
+   IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will
+   search the MCA slots until it finds a 3c523 with the specified
+   parameters.
 
-  This driver should support multiple ethernet cards, but I can't test
-  that.  If someone would I'd greatly appreciate it.
+   This driver should support multiple ethernet cards, but I can't test
+   that.  If someone would I'd greatly appreciate it.
 
-  This has been tested with both BNC and TP versions, internal and
-  external transceivers.  Haven't tested with the 64K version (that I
-  know of).
+   This has been tested with both BNC and TP versions, internal and
+   external transceivers.  Haven't tested with the 64K version (that I
+   know of).
 
-History:
-  Jan 1st, 1996
-       first public release
-  Feb 4th, 1996
-       update to 1.3.59, incorporated multicast diffs from ni52.c
-  Feb 15th, 1996
-       added shared irq support
+   History:
+   Jan 1st, 1996
+   first public release
+   Feb 4th, 1996
+   update to 1.3.59, incorporated multicast diffs from ni52.c
+   Feb 15th, 1996
+   added shared irq support
 
-  $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
-*/
+   $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
+ */
 
 #ifdef MODULE
 #include <linux/module.h>
@@ -105,8 +105,8 @@ History:
 #include "3c523.h"
 
 /*************************************************************************/
-#define DEBUG       /* debug on */
-#define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit*/
+#define DEBUG                  /* debug on */
+#define SYSBUSVAL 0            /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */
 
 #define make32(ptr16) (p->memtop + (short) (ptr16) )
 #define make24(ptr32) ((char *) (ptr32) - p->base)
@@ -114,11 +114,19 @@ History:
 
 /*************************************************************************/
 /*
-    Tables to which we can map values in the configuration registers.
-*/
-static int irq_table[] __initdata = {12, 7, 3, 9};
-static int csr_table[] __initdata = {0x300, 0x1300, 0x2300, 0x3300};
-static int shm_table[] __initdata = {0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000};
+   Tables to which we can map values in the configuration registers.
+ */
+static int irq_table[] __initdata = {
+       12, 7, 3, 9
+};
+
+static int csr_table[] __initdata = {
+       0x300, 0x1300, 0x2300, 0x3300
+};
+
+static int shm_table[] __initdata = {
+       0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000
+};
 
 /******************* how to calculate the buffers *****************************
 
@@ -135,21 +143,21 @@ sizeof(nop_cmd) = 8;
 
   * if you don't know the driver, better do not change this values: */
 
-#define RECV_BUFF_SIZE 1524 /* slightly oversized */
-#define XMIT_BUFF_SIZE 1524 /* slightly oversized */
-#define NUM_XMIT_BUFFS 4    /* config for both, 8K and 16K shmem */
-#define NUM_RECV_BUFFS_8  1 /* config for 8K shared mem */
-#define NUM_RECV_BUFFS_16 6 /* config for 16K shared mem */
+#define RECV_BUFF_SIZE 1524    /* slightly oversized */
+#define XMIT_BUFF_SIZE 1524    /* slightly oversized */
+#define NUM_XMIT_BUFFS 4       /* config for both, 8K and 16K shmem */
+#define NUM_RECV_BUFFS_8  1    /* config for 8K shared mem */
+#define NUM_RECV_BUFFS_16 6    /* config for 16K shared mem */
 
 #if (NUM_XMIT_BUFFS == 1)
-#define NO_NOPCOMMANDS      /* only possible with NUM_XMIT_BUFFS=1 */
+#define NO_NOPCOMMANDS         /* only possible with NUM_XMIT_BUFFS=1 */
 #endif
 
 /**************************************************************************/
 
 #define DELAY(x) {int i=jiffies; \
                   if(loops_per_sec == 1) \
-                     while(i+(x)>jiffies); \
+                     while(time_after(i+(x), jiffies)); \
                   else \
                      __delay((loops_per_sec>>5)*x); \
                  }
@@ -167,42 +175,41 @@ sizeof(nop_cmd) = 8;
        dev->name,__LINE__); \
       elmc_id_reset586(); } } }
 
-static void    elmc_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
-static int     elmc_open(struct device *dev);
-static int     elmc_close(struct device *dev);
-static int     elmc_send_packet(struct sk_buff *,struct device *);
-static struct  net_device_stats *elmc_get_stats(struct device *dev);
-static void    set_multicast_list(struct device *dev);
+static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
+static int elmc_open(struct device *dev);
+static int elmc_close(struct device *dev);
+static int elmc_send_packet(struct sk_buff *, struct device *);
+static struct net_device_stats *elmc_get_stats(struct device *dev);
+static void set_multicast_list(struct device *dev);
 
 /* helper-functions */
-static int     init586(struct device *dev);
-static int     check586(struct device *dev,char *where,unsigned size);
-static void    alloc586(struct device *dev);
-static void    startrecv586(struct device *dev);
-static void   *alloc_rfa(struct device *dev,void *ptr);
-static void    elmc_rcv_int(struct device *dev);
-static void    elmc_xmt_int(struct device *dev);
-static void    elmc_rnr_int(struct device *dev);
-
-struct priv 
-{
+static int init586(struct device *dev);
+static int check586(struct device *dev, char *where, unsigned size);
+static void alloc586(struct device *dev);
+static void startrecv586(struct device *dev);
+static void *alloc_rfa(struct device *dev, void *ptr);
+static void elmc_rcv_int(struct device *dev);
+static void elmc_xmt_int(struct device *dev);
+static void elmc_rnr_int(struct device *dev);
+
+struct priv {
        struct net_device_stats stats;
        unsigned long base;
        char *memtop;
-       volatile struct rfd_struct      *rfd_last,*rfd_top,*rfd_first;
-       volatile struct scp_struct      *scp;   /* volatile is important */
-       volatile struct iscp_struct *iscp; /* volatile is important */
-       volatile struct scb_struct  *scb;  /* volatile is important */
-       volatile struct tbd_struct  *xmit_buffs[NUM_XMIT_BUFFS];
+       volatile struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
+       volatile struct scp_struct *scp;        /* volatile is important */
+       volatile struct iscp_struct *iscp;      /* volatile is important */
+       volatile struct scb_struct *scb;        /* volatile is important */
+       volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS];
        volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
 #if (NUM_XMIT_BUFFS == 1)
        volatile struct nop_cmd_struct *nop_cmds[2];
 #else
        volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
 #endif
-       volatile int    nop_point,num_recv_buffs;
-       volatile char  *xmit_cbuffs[NUM_XMIT_BUFFS];
-       volatile int    xmit_count,xmit_last;
+       volatile int nop_point, num_recv_buffs;
+       volatile char *xmit_cbuffs[NUM_XMIT_BUFFS];
+       volatile int xmit_count, xmit_last;
        volatile int slot;
 };
 
@@ -210,379 +217,368 @@ struct priv
 #define elmc_reset586() {elmc_do_reset586(dev->base_addr,ELMC_CTRL_INTE);}
 
 /* with interrupts disabled - this will clear the interrupt bit in the
-3c523 control register, and won't put it back.  This effectively
-disables interrupts on the card. */
+   3c523 control register, and won't put it back.  This effectively
+   disables interrupts on the card. */
 #define elmc_id_attn586()  {elmc_do_attn586(dev->base_addr,0);}
 #define elmc_id_reset586() {elmc_do_reset586(dev->base_addr,0);}
 
 /*************************************************************************/
 /*
-       Do a Channel Attention on the 3c523.  This is extremely board dependent.
-*/
-static
-void
-elmc_do_attn586( int ioaddr, int ints ) {
-    /* the 3c523 requires a minimum of 500 ns.  The delays here might be
-    a little too large, and hence they may cut the performance of the
-    card slightly.  If someone who knows a little more about Linux
-    timing would care to play with these, I'd appreciate it. */
-
-    /* this bit masking stuff is crap.  I'd rather have separate
-    registers with strobe triggers for each of these functions.  <sigh>
-    Ya take what ya got. */
-
-    outb( ELMC_CTRL_RST|0x3|ELMC_CTRL_CA|ints, ioaddr + ELMC_CTRL);
-    DELAY_16();        /* > 500 ns */
-    outb( ELMC_CTRL_RST|0x3|ints, ioaddr + ELMC_CTRL);
+   Do a Channel Attention on the 3c523.  This is extremely board dependent.
+ */
+static void elmc_do_attn586(int ioaddr, int ints)
+{
+       /* the 3c523 requires a minimum of 500 ns.  The delays here might be
+          a little too large, and hence they may cut the performance of the
+          card slightly.  If someone who knows a little more about Linux
+          timing would care to play with these, I'd appreciate it. */
+
+       /* this bit masking stuff is crap.  I'd rather have separate
+          registers with strobe triggers for each of these functions.  <sigh>
+          Ya take what ya got. */
+
+       outb(ELMC_CTRL_RST | 0x3 | ELMC_CTRL_CA | ints, ioaddr + ELMC_CTRL);
+       DELAY_16();             /* > 500 ns */
+       outb(ELMC_CTRL_RST | 0x3 | ints, ioaddr + ELMC_CTRL);
 }
 
 /*************************************************************************/
 /*
-       Reset the 82586 on the 3c523.  Also very board dependent.
-*/
-static
-void
-elmc_do_reset586( int ioaddr, int ints ) {
-    /* toggle the RST bit low then high */
-    outb( 0x3|ELMC_CTRL_LBK, ioaddr + ELMC_CTRL );
-    DELAY_16();        /* > 500 ns */
-    outb( ELMC_CTRL_RST|ELMC_CTRL_LBK|0x3, ioaddr + ELMC_CTRL );
-
-       elmc_do_attn586( ioaddr, ints );
+   Reset the 82586 on the 3c523.  Also very board dependent.
+ */
+static void elmc_do_reset586(int ioaddr, int ints)
+{
+       /* toggle the RST bit low then high */
+       outb(0x3 | ELMC_CTRL_LBK, ioaddr + ELMC_CTRL);
+       DELAY_16();             /* > 500 ns */
+       outb(ELMC_CTRL_RST | ELMC_CTRL_LBK | 0x3, ioaddr + ELMC_CTRL);
+
+       elmc_do_attn586(ioaddr, ints);
 }
 
 /**********************************************
  * close device
  */
 
-static
-int
-elmc_close(struct device *dev) {
-  elmc_id_reset586(); /* the hard way to stop the receiver */
+static int elmc_close(struct device *dev)
+{
+       elmc_id_reset586();     /* the hard way to stop the receiver */
 
-  free_irq(dev->irq, dev);
+       free_irq(dev->irq, dev);
 
-  dev->start = 0;
-  dev->tbusy = 0;
+       dev->start = 0;
+       dev->tbusy = 0;
 
 #ifdef MODULE
        MOD_DEC_USE_COUNT;
 #endif
 
-  return 0;
+       return 0;
 }
 
 /**********************************************
  * open device
  */
 
-static
-int
-elmc_open(struct device *dev) {
-
-  elmc_id_attn586();   /* disable interrupts */
+static int elmc_open(struct device *dev)
+{
 
-  if(request_irq( dev->irq, &elmc_interrupt, SA_SHIRQ|SA_SAMPLE_RANDOM,
-       "3c523", dev )
-  ) {
-    printk( "%s: couldn't get irq %d\n", dev->name, dev->irq );
-    elmc_id_reset586();
-    return -EAGAIN;
-  }
+       elmc_id_attn586();      /* disable interrupts */
 
-  alloc586(dev);
-  init586(dev);
-  startrecv586(dev);
+       if (request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM,
+                       "3c523", dev)
+           ) {
+               printk("%s: couldn't get irq %d\n", dev->name, dev->irq);
+               elmc_id_reset586();
+               return -EAGAIN;
+       }
+       alloc586(dev);
+       init586(dev);
+       startrecv586(dev);
 
-  dev->interrupt = 0;
-  dev->tbusy = 0;
-  dev->start = 1;
+       dev->interrupt = 0;
+       dev->tbusy = 0;
+       dev->start = 1;
 
 #ifdef MODULE
        MOD_INC_USE_COUNT;
 #endif
 
-  return 0; /* most done by init */
+       return 0;               /* most done by init */
 }
 
 /**********************************************
  * Check to see if there's an 82586 out there.
  */
 
-__initfunc(static
-int
-check586( struct device *dev, char *where, unsigned size)) {
-  struct priv *p = (struct priv *) dev->priv;
-  char *iscp_addrs[2];
-  int i = 0;
-
-  p->base = (unsigned long) where + size - 0x01000000;
-  p->memtop = where + size;
-  p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
-  memset((char *)p->scp,0, sizeof(struct scp_struct));
-  p->scp->sysbus = SYSBUSVAL;        /* 1 = 8Bit-Bus, 0 = 16 Bit */
+__initfunc(static int check586(struct device *dev, char *where, unsigned size))
+{
+       struct priv *p = (struct priv *) dev->priv;
+       char *iscp_addrs[2];
+       int i = 0;
 
-  iscp_addrs[0] = where;
-  iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
+       p->base = (unsigned long) where + size - 0x01000000;
+       p->memtop = where + size;
+       p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+       memset((char *) p->scp, 0, sizeof(struct scp_struct));
+       p->scp->sysbus = SYSBUSVAL;     /* 1 = 8Bit-Bus, 0 = 16 Bit */
 
-  for( i = 0; i < 2; i ++ ) {
-    p->iscp = (struct iscp_struct *) iscp_addrs[i];
-    memset((char *)p->iscp,0, sizeof(struct iscp_struct));
+       iscp_addrs[0] = where;
+       iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
 
-    p->scp->iscp = make24(p->iscp);
-    p->iscp->busy = 1;
+       for (i = 0; i < 2; i++) {
+               p->iscp = (struct iscp_struct *) iscp_addrs[i];
+               memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
 
-    elmc_id_reset586();
+               p->scp->iscp = make24(p->iscp);
+               p->iscp->busy = 1;
 
-    /* reset586 does an implicit CA */
+               elmc_id_reset586();
 
-    /* apparently, you sometimes have to kick the 82586 twice... */
-    elmc_id_attn586();
+               /* reset586 does an implicit CA */
 
-    if(p->iscp->busy) { /* i82586 clears 'busy' after successful init */
-      return 0;
-    }
-  }
+               /* apparently, you sometimes have to kick the 82586 twice... */
+               elmc_id_attn586();
 
-  return 1;
+               if (p->iscp->busy) {    /* i82586 clears 'busy' after successful init */
+                       return 0;
+               }
+       }
+       return 1;
 }
 
 /******************************************************************
  * set iscp at the right place, called by elmc_probe and open586.
  */
 
-void
-alloc586( struct device *dev ) {
-  struct priv *p =  (struct priv *) dev->priv;
-
-  elmc_id_reset586();
-  DELAY(2);
+void alloc586(struct device *dev)
+{
+       struct priv *p = (struct priv *) dev->priv;
 
-  p->scp  = (struct scp_struct *)  (p->base + SCP_DEFAULT_ADDRESS);
-  p->scb  = (struct scb_struct *)  (dev->mem_start);
-  p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
+       elmc_id_reset586();
+       DELAY(2);
 
-  memset((char *) p->iscp,0,sizeof(struct iscp_struct));
-  memset((char *) p->scp ,0,sizeof(struct scp_struct));
+       p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+       p->scb = (struct scb_struct *) (dev->mem_start);
+       p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
 
-  p->scp->iscp = make24(p->iscp);
-  p->scp->sysbus = SYSBUSVAL;
-  p->iscp->scb_offset = make16(p->scb);
+       memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
+       memset((char *) p->scp, 0, sizeof(struct scp_struct));
 
-  p->iscp->busy = 1;
-  elmc_id_reset586();
-  elmc_id_attn586();
+       p->scp->iscp = make24(p->iscp);
+       p->scp->sysbus = SYSBUSVAL;
+       p->iscp->scb_offset = make16(p->scb);
 
-  DELAY(2);
+       p->iscp->busy = 1;
+       elmc_id_reset586();
+       elmc_id_attn586();
 
-  if(p->iscp->busy) {
-    printk("%s: Init-Problems (alloc).\n",dev->name);
-  }
+       DELAY(2);
 
-  memset((char *)p->scb,0,sizeof(struct scb_struct));
+       if (p->iscp->busy) {
+               printk("%s: Init-Problems (alloc).\n", dev->name);
+       }
+       memset((char *) p->scb, 0, sizeof(struct scb_struct));
 }
 
 /*****************************************************************/
-static int
-elmc_getinfo( char* buf, int slot, void* d ) {
+
+static int elmc_getinfo(char *buf, int slot, void *d)
+{
        int len = 0;
-       struct device* dev = (struct device*) d;
+       struct device *dev = (struct device *) d;
        int i;
 
-       if( dev == NULL ) return len;
-
-       len += sprintf( buf+len, "Revision: 0x%x\n",
-               inb( dev->base_addr + ELMC_REVISION ) & 0xf );
-       len += sprintf( buf+len, "IRQ: %d\n", dev->irq );
-       len += sprintf( buf+len, "IO Address: %#lx-%#lx\n", dev->base_addr,
-               dev->base_addr+ELMC_IO_EXTENT );
-       len += sprintf( buf+len, "Memory: %#lx-%#lx\n", dev->mem_start,
-               dev->mem_end-1 );
-       len += sprintf( buf+len, "Transceiver: %s\n", dev->if_port ?
-               "External" : "Internal" );
-       len += sprintf( buf+len, "Device: %s\n", dev->name );
-       len += sprintf( buf+len, "Hardware Address:" );
-       for (i = 0; i < 6; i ++ ) {
-               len += sprintf( buf+len, " %02x", dev->dev_addr[i] );
+       if (dev == NULL)
+               return len;
+
+       len += sprintf(buf + len, "Revision: 0x%x\n",
+                      inb(dev->base_addr + ELMC_REVISION) & 0xf);
+       len += sprintf(buf + len, "IRQ: %d\n", dev->irq);
+       len += sprintf(buf + len, "IO Address: %#lx-%#lx\n", dev->base_addr,
+                      dev->base_addr + ELMC_IO_EXTENT);
+       len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
+                      dev->mem_end - 1);
+       len += sprintf(buf + len, "Transceiver: %s\n", dev->if_port ?
+                      "External" : "Internal");
+       len += sprintf(buf + len, "Device: %s\n", dev->name);
+       len += sprintf(buf + len, "Hardware Address:");
+       for (i = 0; i < 6; i++) {
+               len += sprintf(buf + len, " %02x", dev->dev_addr[i]);
        }
        buf[len++] = '\n';
        buf[len] = 0;
 
        return len;
-} /* elmc_getinfo() */
+}                              /* elmc_getinfo() */
 
 /*****************************************************************/
-__initfunc(int
-elmc_probe(struct device *dev)) {
-    static int slot = 0;
-    int base_addr = dev ? dev->base_addr : 0;
-    int irq = dev ? dev->irq : 0;
-    u_char status = 0;
-    u_char revision = 0;
-    int i = 0;
-    unsigned int size = 0;
-
-    if( MCA_bus == 0 ) {
-       return ENODEV;
-    }
 
+__initfunc(int elmc_probe(struct device *dev))
+{
+       static int slot = 0;
+       int base_addr = dev ? dev->base_addr : 0;
+       int irq = dev ? dev->irq : 0;
+       u_char status = 0;
+       u_char revision = 0;
+       int i = 0;
+       unsigned int size = 0;
+
+       if (MCA_bus == 0) {
+               return ENODEV;
+       }
        /* search through the slots for the 3c523. */
-       slot = mca_find_adapter( ELMC_MCA_ID, 0 );
-       while( slot != -1 ) {
-               status = mca_read_stored_pos( slot, 2 );
+       slot = mca_find_adapter(ELMC_MCA_ID, 0);
+       while (slot != -1) {
+               status = mca_read_stored_pos(slot, 2);
 
                /*
-                       If we're trying to match a specified irq or IO address,
-                       we'll reject a match unless it's what we're looking for.
-               */
-               if( base_addr || irq ) {
+                  If we're trying to match a specified irq or IO address,
+                  we'll reject a match unless it's what we're looking for.
+                */
+               if (base_addr || irq) {
                        /* we're looking for a card at a particular place */
 
-                       if( irq &&
-                               irq != irq_table[ (status & ELMC_STATUS_IRQ_SELECT) >> 6]
-                       ) {
-                               slot = mca_find_adapter( ELMC_MCA_ID, slot + 1 );
+                       if (irq && irq != irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]) {
+                               slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
                                continue;
                        }
-
-                       if( base_addr && base_addr !=
-                               csr_table[ (status & ELMC_STATUS_CSR_SELECT) >> 1]
-                       ) {
-                               slot = mca_find_adapter( ELMC_MCA_ID, slot + 1 );
+                       if (base_addr && base_addr != csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]) {
+                               slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
                                continue;
                        }
                }
-
                /* found what we're looking for... */
                break;
        }
 
        /* we didn't find any 3c523 in the slots we checked for */
-       if( slot == MCA_NOTFOUND ) {
+       if (slot == MCA_NOTFOUND) {
                return ((base_addr || irq) ? ENXIO : ENODEV);
        }
+       mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
+       mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
+
+       /* if we get this far, adapter has been found - carry on */
+       printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
+
+       /* Now we extract configuration info from the card.
+          The 3c523 provides information in two of the POS registers, but
+          the second one is only needed if we want to tell the card what IRQ
+          to use.  I suspect that whoever sets the thing up initially would
+          prefer we don't screw with those things.
+
+          Note that we read the status info when we found the card...
+
+          See 3c523.h for more details.
+        */
+
+       /* revision is stored in the first 4 bits of the revision register */
+       revision = inb(dev->base_addr + ELMC_REVISION) & 0xf;
+
+       /* figure out our irq */
+       dev->irq = irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6];
+
+       /* according to docs, we read the interrupt and write it back to
+          the IRQ select register, since the POST might not configure the IRQ
+          properly. */
+       switch (dev->irq) {
+       case 3:
+               mca_write_pos(slot, 3, 0x04);
+               break;
+       case 7:
+               mca_write_pos(slot, 3, 0x02);
+               break;
+       case 9:
+               mca_write_pos(slot, 3, 0x08);
+               break;
+       case 12:
+               mca_write_pos(slot, 3, 0x01);
+               break;
+       }
+
+       /* Our IO address? */
+       dev->base_addr = csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1];
+
+       request_region(dev->base_addr, ELMC_IO_EXTENT, "3c523");
+
+       dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL);
+       if (dev->priv == NULL) {
+               return -ENOMEM;
+       }
+       memset((char *) dev->priv, 0, sizeof(struct priv));
+
+       ((struct priv *) (dev->priv))->slot = slot;
+
+       printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
+              dev->base_addr);
+
+       /* Determine if we're using the on-board transceiver (i.e. coax) or
+          an external one.  The information is pretty much useless, but I
+          guess it's worth brownie points. */
+       dev->if_port = (status & ELMC_STATUS_DISABLE_THIN);
+
+       /* The 3c523 has a 24K chunk of memory.  The first 16K is the
+          shared memory, while the last 8K is for the EtherStart BIOS ROM.
+          Which we don't care much about here.  We'll just tell Linux that
+          we're using 16K.  MCA won't permit adress space conflicts caused
+          by not mapping the other 8K. */
+       dev->mem_start = phys_to_virt(shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]);
+
+       /* We're using MCA, so it's a given that the information about memory
+          size is correct.  The Crynwr drivers do something like this. */
+
+       elmc_id_reset586();     /* seems like a good idea before checking it... */
+
+       size = 0x4000;          /* check for 16K mem */
+       if (!check586(dev, (char *) dev->mem_start, size)) {
+               printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
+                      dev->mem_start);
+               release_region(dev->base_addr, ELMC_IO_EXTENT);
+               return ENODEV;
+       }
+       dev->mem_end = dev->mem_start + size;   /* set mem_end showed by 'ifconfig' */
+
+       ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000;
+       alloc586(dev);
+
+       elmc_id_reset586();     /* make sure it doesn't generate spurious ints */
+
+       /* set number of receive-buffs according to memsize */
+       ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
+
+       /* dump all the assorted information */
+       printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
+              dev->irq, dev->if_port ? "ex" : "in", 
+              virt_to_phys(dev->mem_start), 
+              virt_to_phys(dev->mem_end - 1));
+
+       /* The hardware address for the 3c523 is stored in the first six
+          bytes of the IO address. */
+       printk("%s: hardware address ", dev->name);
+       for (i = 0; i < 6; i++) {
+               dev->dev_addr[i] = inb(dev->base_addr + i);
+               printk(" %02x", dev->dev_addr[i]);
+       }
+       printk("\n");
+
+       dev->open = &elmc_open;
+       dev->stop = &elmc_close;
+       dev->get_stats = &elmc_get_stats;
+       dev->hard_start_xmit = &elmc_send_packet;
+       dev->set_multicast_list = &set_multicast_list;
+
+       ether_setup(dev);
 
-       mca_set_adapter_name( slot, "3Com 3c523 Etherlink/MC" );
-       mca_set_adapter_procfn( slot, (MCA_ProcFn) elmc_getinfo, dev );
-
-    /* if we get this far, adapter has been found - carry on */
-    printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
-
-    /* Now we extract configuration info from the card.
-       The 3c523 provides information in two of the POS registers, but
-       the second one is only needed if we want to tell the card what IRQ
-       to use.  I suspect that whoever sets the thing up initially would
-       prefer we don't screw with those things.
-
-       Note that we read the status info when we found the card...
-
-       See 3c523.h for more details.
-       */
-
-    /* revision is stored in the first 4 bits of the revision register */
-    revision = inb( dev->base_addr + ELMC_REVISION ) & 0xf;
-
-    /* figure out our irq */
-    dev->irq = irq_table[ (status & ELMC_STATUS_IRQ_SELECT) >> 6];
-
-    /* according to docs, we read the interrupt and write it back to
-    the IRQ select register, since the POST might not configure the IRQ
-    properly. */
-    switch( dev->irq ) {
-       case 3:
-               mca_write_pos( slot, 3, 0x04 );
-               break;
-       case 7:
-               mca_write_pos( slot, 3, 0x02 );
-               break;
-       case 9:
-               mca_write_pos( slot, 3, 0x08 );
-               break;
-       case 12:
-               mca_write_pos( slot, 3, 0x01 );
-               break;
-    }
-
-    /* Our IO address? */
-    dev->base_addr = csr_table[ (status & ELMC_STATUS_CSR_SELECT) >> 1];
-
-    request_region( dev->base_addr, ELMC_IO_EXTENT,"3c523");
-
-    dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);
-    if (dev->priv == NULL) {
-       return -ENOMEM;
-    }
-    memset((char *) dev->priv,0,sizeof(struct priv));
-
-    ((struct priv *) (dev->priv))->slot = slot;
-
-    printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
-       dev->base_addr);
-
-    /* Determine if we're using the on-board transceiver (i.e. coax) or
-        an external one.  The information is pretty much useless, but I
-        guess it's worth brownie points. */
-    dev->if_port = (status & ELMC_STATUS_DISABLE_THIN);
-
-    /* The 3c523 has a 24K chunk of memory.  The first 16K is the
-        shared memory, while the last 8K is for the EtherStart BIOS ROM.
-        Which we don't care much about here.  We'll just tell Linux that
-        we're using 16K.  MCA won't permit adress space conflicts caused
-        by not mapping the other 8K. */
-    dev->mem_start = shm_table[ (status & ELMC_STATUS_MEMORY_SELECT) >> 3];
-
-  /* We're using MCA, so it's a given that the information about memory
-       size is correct.  The Crynwr drivers do something like this. */
-
-  elmc_id_reset586();  /* seems like a good idea before checking it... */
-
-  size = 0x4000; /* check for 16K mem */
-  if(!check586(dev,(char *) dev->mem_start,size)) {
-       printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
-               dev->mem_start );
-       release_region( dev->base_addr, ELMC_IO_EXTENT );
-       return ENODEV;
-  }
-  dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
-
-  ((struct priv *) (dev->priv))->base =  dev->mem_start + size - 0x01000000;
-  alloc586(dev);
-
-  elmc_id_reset586();  /* make sure it doesn't generate spurious ints */
-
-  /* set number of receive-buffs according to memsize */
-  ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
-
-  /* dump all the assorted information */
-  printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
-       dev->irq, dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
-
-  /* The hardware address for the 3c523 is stored in the first six
-       bytes of the IO address. */
-  printk( "%s: hardware address ", dev->name );
-  for (i = 0; i < 6; i ++ ) {
-   dev->dev_addr[i] = inb(dev->base_addr + i);
-   printk(" %02x", dev->dev_addr[i]);
-  }
-  printk( "\n" );
-
-  dev->open            = &elmc_open;
-  dev->stop            = &elmc_close;
-  dev->get_stats       = &elmc_get_stats;
-  dev->hard_start_xmit = &elmc_send_packet;
-  dev->set_multicast_list = &set_multicast_list;
-
-  ether_setup(dev);
-
-  dev->tbusy = 0;
-  dev->interrupt = 0;
-  dev->start = 0;
-
-  /* note that we haven't actually requested the IRQ from the kernel.
-  That gets done in elmc_open().  I'm not sure that's such a good idea,
-  but it works, so I'll go with it. */
-
-  return 0;
+       dev->tbusy = 0;
+       dev->interrupt = 0;
+       dev->start = 0;
+
+       /* note that we haven't actually requested the IRQ from the kernel.
+          That gets done in elmc_open().  I'm not sure that's such a good idea,
+          but it works, so I'll go with it. */
+
+       return 0;
 }
 
 /**********************************************
@@ -590,241 +586,237 @@ elmc_probe(struct device *dev)) {
  * needs a correct 'allocated' memory
  */
 
-static
-int
-init586(struct device *dev) {
-  void *ptr;
-  unsigned long s;
-  int i,result=0;
-  struct priv *p = (struct priv *) dev->priv;
-  volatile struct configure_cmd_struct  *cfg_cmd;
-  volatile struct iasetup_cmd_struct *ias_cmd;
-  volatile struct tdr_cmd_struct *tdr_cmd;
-  volatile struct mcsetup_cmd_struct *mc_cmd;
-  struct dev_mc_list *dmi=dev->mc_list;
-  int num_addrs=dev->mc_count;
-
-  ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
-
-  cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
-  cfg_cmd->cmd_status = 0;
-  cfg_cmd->cmd_cmd    = CMD_CONFIGURE | CMD_LAST;
-  cfg_cmd->cmd_link   = 0xffff;
-
-  cfg_cmd->byte_cnt   = 0x0a; /* number of cfg bytes */
-  cfg_cmd->fifo       = 0x08; /* fifo-limit (8=tx:32/rx:64) */
-  cfg_cmd->sav_bf     = 0x40; /* hold or discard bad recv frames (bit 7) */
-  cfg_cmd->adr_len    = 0x2e; /* addr_len |!src_insert |pre-len |loopback */
-  cfg_cmd->priority   = 0x00;
-  cfg_cmd->ifs        = 0x60;
-  cfg_cmd->time_low   = 0x00;
-  cfg_cmd->time_high  = 0xf2;
-  cfg_cmd->promisc    = 0;
-  if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
-  {
-       cfg_cmd->promisc=1;
-       dev->flags|=IFF_PROMISC;
-  }
-  cfg_cmd->carr_coll  = 0x00;
-
-  p->scb->cbl_offset = make16(cfg_cmd);
-
-  p->scb->cmd = CUC_START; /* cmd.-unit start */
-  elmc_id_attn586();
-
-  s = jiffies; /* warning: only active with interrupts on !! */
-  while(!(cfg_cmd->cmd_status & STAT_COMPL)) {
-    if(jiffies-s > 30) break;
-  }
-
-  if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) {
-    printk("%s (elmc): configure command failed: %x\n",dev->name,cfg_cmd->cmd_status);
-    return 1;
-  }
-
-    /*
-     * individual address setup
-     */
-  ias_cmd = (struct iasetup_cmd_struct *)ptr;
-
-  ias_cmd->cmd_status = 0;
-  ias_cmd->cmd_cmd    = CMD_IASETUP | CMD_LAST;
-  ias_cmd->cmd_link   = 0xffff;
-
-  memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN);
-
-  p->scb->cbl_offset = make16(ias_cmd);
-
-  p->scb->cmd = CUC_START; /* cmd.-unit start */
-  elmc_id_attn586();
-
-  s = jiffies;
-  while(!(ias_cmd->cmd_status & STAT_COMPL))  {
-    if(jiffies-s > 30) break;
-  }
-
-  if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) {
-    printk("%s (elmc): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status);
-    return 1;
-  }
-
-   /*
-    * TDR, wire check .. e.g. no resistor e.t.c
-    */
-  tdr_cmd = (struct tdr_cmd_struct *)ptr;
-
-  tdr_cmd->cmd_status  = 0;
-  tdr_cmd->cmd_cmd     = CMD_TDR | CMD_LAST;
-  tdr_cmd->cmd_link    = 0xffff;
-  tdr_cmd->status      = 0;
-
-  p->scb->cbl_offset = make16(tdr_cmd);
-
-  p->scb->cmd = CUC_START; /* cmd.-unit start */
-  elmc_attn586();
-
-  s = jiffies;
-  while(!(tdr_cmd->cmd_status & STAT_COMPL)) {
-    if(jiffies - s > 30) {
-      printk("%s: %d Problems while running the TDR.\n",dev->name,__LINE__);
-      result = 1;
-      break;
-    }
-  }
-
-  if(!result) {
-    DELAY(2); /* wait for result */
-    result = tdr_cmd->status;
-
-    p->scb->cmd = p->scb->status & STAT_MASK;
-    elmc_id_attn586(); /* ack the interrupts */
-
-    if(result & TDR_LNK_OK) {
-       /* empty */
-    } else if(result & TDR_XCVR_PRB) {
-      printk("%s: TDR: Transceiver problem!\n",dev->name);
-    } else if(result & TDR_ET_OPN) {
-      printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
-    } else if(result & TDR_ET_SRT) {
-      if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */
-        printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
-    } else {
-      printk("%s: TDR: Unknown status %04x\n",dev->name,result);
-    }
-  }
-
-   /*
-    * ack interrupts
-    */
-  p->scb->cmd = p->scb->status & STAT_MASK;
-  elmc_id_attn586();
-
-   /*
-    * alloc nop/xmit-cmds
-    */
+static int init586(struct device *dev)
+{
+       void *ptr;
+       unsigned long s;
+       int i, result = 0;
+       struct priv *p = (struct priv *) dev->priv;
+       volatile struct configure_cmd_struct *cfg_cmd;
+       volatile struct iasetup_cmd_struct *ias_cmd;
+       volatile struct tdr_cmd_struct *tdr_cmd;
+       volatile struct mcsetup_cmd_struct *mc_cmd;
+       struct dev_mc_list *dmi = dev->mc_list;
+       int num_addrs = dev->mc_count;
+
+       ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct));
+
+       cfg_cmd = (struct configure_cmd_struct *) ptr;  /* configure-command */
+       cfg_cmd->cmd_status = 0;
+       cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST;
+       cfg_cmd->cmd_link = 0xffff;
+
+       cfg_cmd->byte_cnt = 0x0a;       /* number of cfg bytes */
+       cfg_cmd->fifo = 0x08;   /* fifo-limit (8=tx:32/rx:64) */
+       cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */
+       cfg_cmd->adr_len = 0x2e;        /* addr_len |!src_insert |pre-len |loopback */
+       cfg_cmd->priority = 0x00;
+       cfg_cmd->ifs = 0x60;
+       cfg_cmd->time_low = 0x00;
+       cfg_cmd->time_high = 0xf2;
+       cfg_cmd->promisc = 0;
+       if (dev->flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+               cfg_cmd->promisc = 1;
+               dev->flags |= IFF_PROMISC;
+       }
+       cfg_cmd->carr_coll = 0x00;
+
+       p->scb->cbl_offset = make16(cfg_cmd);
+
+       p->scb->cmd = CUC_START;        /* cmd.-unit start */
+       elmc_id_attn586();
+
+       s = jiffies;            /* warning: only active with interrupts on !! */
+       while (!(cfg_cmd->cmd_status & STAT_COMPL)) {
+               if (jiffies - s > 30)
+                       break;
+       }
+
+       if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) {
+               printk("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
+               return 1;
+       }
+       /*
+        * individual address setup
+        */
+       ias_cmd = (struct iasetup_cmd_struct *) ptr;
+
+       ias_cmd->cmd_status = 0;
+       ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST;
+       ias_cmd->cmd_link = 0xffff;
+
+       memcpy((char *) &ias_cmd->iaddr, (char *) dev->dev_addr, ETH_ALEN);
+
+       p->scb->cbl_offset = make16(ias_cmd);
+
+       p->scb->cmd = CUC_START;        /* cmd.-unit start */
+       elmc_id_attn586();
+
+       s = jiffies;
+       while (!(ias_cmd->cmd_status & STAT_COMPL)) {
+               if (jiffies - s > 30)
+                       break;
+       }
+
+       if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) {
+               printk("%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status);
+               return 1;
+       }
+       /*
+        * TDR, wire check .. e.g. no resistor e.t.c
+        */
+       tdr_cmd = (struct tdr_cmd_struct *) ptr;
+
+       tdr_cmd->cmd_status = 0;
+       tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST;
+       tdr_cmd->cmd_link = 0xffff;
+       tdr_cmd->status = 0;
+
+       p->scb->cbl_offset = make16(tdr_cmd);
+
+       p->scb->cmd = CUC_START;        /* cmd.-unit start */
+       elmc_attn586();
+
+       s = jiffies;
+       while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
+               if (jiffies - s > 30) {
+                       printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
+                       result = 1;
+                       break;
+               }
+       }
+
+       if (!result) {
+               DELAY(2);       /* wait for result */
+               result = tdr_cmd->status;
+
+               p->scb->cmd = p->scb->status & STAT_MASK;
+               elmc_id_attn586();      /* ack the interrupts */
+
+               if (result & TDR_LNK_OK) {
+                       /* empty */
+               } else if (result & TDR_XCVR_PRB) {
+                       printk("%s: TDR: Transceiver problem!\n", dev->name);
+               } else if (result & TDR_ET_OPN) {
+                       printk("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+               } else if (result & TDR_ET_SRT) {
+                       if (result & TDR_TIMEMASK)      /* time == 0 -> strange :-) */
+                               printk("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+               } else {
+                       printk("%s: TDR: Unknown status %04x\n", dev->name, result);
+               }
+       }
+       /*
+        * ack interrupts
+        */
+       p->scb->cmd = p->scb->status & STAT_MASK;
+       elmc_id_attn586();
+
+       /*
+        * alloc nop/xmit-cmds
+        */
 #if (NUM_XMIT_BUFFS == 1)
-  for(i=0;i<2;i++) {
-    p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
-    p->nop_cmds[i]->cmd_cmd    = CMD_NOP;
-    p->nop_cmds[i]->cmd_status = 0;
-    p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));
-    ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
-  }
-  p->xmit_cmds[0] = (struct transmit_cmd_struct *)ptr; /* transmit cmd/buff 0 */
-  ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
+       for (i = 0; i < 2; i++) {
+               p->nop_cmds[i] = (struct nop_cmd_struct *) ptr;
+               p->nop_cmds[i]->cmd_cmd = CMD_NOP;
+               p->nop_cmds[i]->cmd_status = 0;
+               p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i]));
+               ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
+       }
+       p->xmit_cmds[0] = (struct transmit_cmd_struct *) ptr;   /* transmit cmd/buff 0 */
+       ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
 #else
-  for(i=0;i<NUM_XMIT_BUFFS;i++) {
-    p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
-    p->nop_cmds[i]->cmd_cmd    = CMD_NOP;
-    p->nop_cmds[i]->cmd_status = 0;
-    p->nop_cmds[i]->cmd_link   = make16((p->nop_cmds[i]));
-    ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
-    p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/
-    ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
-  }
+       for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+               p->nop_cmds[i] = (struct nop_cmd_struct *) ptr;
+               p->nop_cmds[i]->cmd_cmd = CMD_NOP;
+               p->nop_cmds[i]->cmd_status = 0;
+               p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i]));
+               ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
+               p->xmit_cmds[i] = (struct transmit_cmd_struct *) ptr;   /*transmit cmd/buff 0 */
+               ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
+       }
 #endif
 
-  ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */
-
-  /*
-   * Multicast setup
-   */
-
-  if(dev->mc_count) {
-    /* I don't understand this: do we really need memory after the init? */
-    int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
-    if(len <= 0) {
-      printk("%s: Ooooops, no memory for MC-Setup!\n",dev->name);
-    } else {
-      if(len < num_addrs) {
-        num_addrs = len;
-        printk("%s: Sorry, can only apply %d MC-Address(es).\n",
-           dev->name, num_addrs);
-      }
-      mc_cmd = (struct mcsetup_cmd_struct *) ptr;
-      mc_cmd->cmd_status = 0;
-      mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
-      mc_cmd->cmd_link = 0xffff;
-      mc_cmd->mc_cnt = num_addrs * 6;
-      for(i=0;i<num_addrs;i++) {
-           memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6);
-           dmi=dmi->next;
-      }
-      p->scb->cbl_offset = make16(mc_cmd);
-      p->scb->cmd = CUC_START;
-      elmc_id_attn586();
-      s = jiffies;
-      while(!(mc_cmd->cmd_status & STAT_COMPL)) {
-        if(jiffies - s > 30)
-          break;
-         }
-      if(!(mc_cmd->cmd_status & STAT_COMPL)) {
-        printk("%s: Can't apply multicast-address-list.\n",dev->name);
-         }
-    }
-  }
-
-  /*
-   * alloc xmit-buffs / init xmit_cmds
-   */
-  for(i=0;i<NUM_XMIT_BUFFS;i++) {
-    p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
-    ptr = (char *) ptr + XMIT_BUFF_SIZE;
-    p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
-    ptr = (char *) ptr + sizeof(struct tbd_struct);
-    if((void *)ptr > (void *)p->iscp) {
-      printk("%s: not enough shared-mem for your configuration!\n",dev->name);
-      return 1;
-    }
-    memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));
-    memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));
-    p->xmit_cmds[i]->cmd_status = STAT_COMPL;
-    p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
-    p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
-    p->xmit_buffs[i]->next = 0xffff;
-    p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
-  }
-
-  p->xmit_count = 0;
-  p->xmit_last  = 0;
+       ptr = alloc_rfa(dev, (void *) ptr);     /* init receive-frame-area */
+
+       /*
+        * Multicast setup
+        */
+
+       if (dev->mc_count) {
+               /* I don't understand this: do we really need memory after the init? */
+               int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
+               if (len <= 0) {
+                       printk("%s: Ooooops, no memory for MC-Setup!\n", dev->name);
+               } else {
+                       if (len < num_addrs) {
+                               num_addrs = len;
+                               printk("%s: Sorry, can only apply %d MC-Address(es).\n",
+                                      dev->name, num_addrs);
+                       }
+                       mc_cmd = (struct mcsetup_cmd_struct *) ptr;
+                       mc_cmd->cmd_status = 0;
+                       mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
+                       mc_cmd->cmd_link = 0xffff;
+                       mc_cmd->mc_cnt = num_addrs * 6;
+                       for (i = 0; i < num_addrs; i++) {
+                               memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr, 6);
+                               dmi = dmi->next;
+                       }
+                       p->scb->cbl_offset = make16(mc_cmd);
+                       p->scb->cmd = CUC_START;
+                       elmc_id_attn586();
+                       s = jiffies;
+                       while (!(mc_cmd->cmd_status & STAT_COMPL)) {
+                               if (jiffies - s > 30)
+                                       break;
+                       }
+                       if (!(mc_cmd->cmd_status & STAT_COMPL)) {
+                               printk("%s: Can't apply multicast-address-list.\n", dev->name);
+                       }
+               }
+       }
+       /*
+        * alloc xmit-buffs / init xmit_cmds
+        */
+       for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+               p->xmit_cbuffs[i] = (char *) ptr;       /* char-buffs */
+               ptr = (char *) ptr + XMIT_BUFF_SIZE;
+               p->xmit_buffs[i] = (struct tbd_struct *) ptr;   /* TBD */
+               ptr = (char *) ptr + sizeof(struct tbd_struct);
+               if ((void *) ptr > (void *) p->iscp) {
+                       printk("%s: not enough shared-mem for your configuration!\n", dev->name);
+                       return 1;
+               }
+               memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct));
+               memset((char *) (p->xmit_buffs[i]), 0, sizeof(struct tbd_struct));
+               p->xmit_cmds[i]->cmd_status = STAT_COMPL;
+               p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
+               p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
+               p->xmit_buffs[i]->next = 0xffff;
+               p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
+       }
+
+       p->xmit_count = 0;
+       p->xmit_last = 0;
 #ifndef NO_NOPCOMMANDS
-  p->nop_point  = 0;
+       p->nop_point = 0;
 #endif
 
-   /*
-    * 'start transmitter' (nop-loop)
-    */
+       /*
+        * 'start transmitter' (nop-loop)
+        */
 #ifndef NO_NOPCOMMANDS
-  p->scb->cbl_offset = make16(p->nop_cmds[0]);
-  p->scb->cmd = CUC_START;
-  elmc_id_attn586();
-  WAIT_4_SCB_CMD();
+       p->scb->cbl_offset = make16(p->nop_cmds[0]);
+       p->scb->cmd = CUC_START;
+       elmc_id_attn586();
+       WAIT_4_SCB_CMD();
 #else
-  p->xmit_cmds[0]->cmd_link = 0xffff;
-  p->xmit_cmds[0]->cmd_cmd  = CMD_XMIT | CMD_LAST | CMD_INT;
+       p->xmit_cmds[0]->cmd_link = 0xffff;
+       p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT;
 #endif
 
-  return 0;
+       return 0;
 }
 
 /******************************************************
@@ -832,44 +824,43 @@ init586(struct device *dev) {
  * It sets up the Receive Frame Area (RFA).
  */
 
-static
-void*
-alloc_rfa(struct device *dev,void *ptr) {
-  volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;
-  volatile struct rbd_struct *rbd;
-  int i;
-  struct priv *p = (struct priv *) dev->priv;
+static void *alloc_rfa(struct device *dev, void *ptr)
+{
+       volatile struct rfd_struct *rfd = (struct rfd_struct *) ptr;
+       volatile struct rbd_struct *rbd;
+       int i;
+       struct priv *p = (struct priv *) dev->priv;
 
-  memset((char *) rfd,0,sizeof(struct rfd_struct)*p->num_recv_buffs);
-  p->rfd_first = rfd;
+       memset((char *) rfd, 0, sizeof(struct rfd_struct) * p->num_recv_buffs);
+       p->rfd_first = rfd;
 
-  for(i = 0; i < p->num_recv_buffs; i++) {
-    rfd[i].next = make16(rfd + (i+1) % p->num_recv_buffs);
-  }
-  rfd[p->num_recv_buffs-1].last = RFD_SUSP;   /* RU suspend */
+       for (i = 0; i < p->num_recv_buffs; i++) {
+               rfd[i].next = make16(rfd + (i + 1) % p->num_recv_buffs);
+       }
+       rfd[p->num_recv_buffs - 1].last = RFD_SUSP;     /* RU suspend */
 
-  ptr = (void *) (rfd + p->num_recv_buffs);
+       ptr = (void *) (rfd + p->num_recv_buffs);
 
-  rbd = (struct rbd_struct *) ptr;
-  ptr = (void *) (rbd + p->num_recv_buffs);
+       rbd = (struct rbd_struct *) ptr;
+       ptr = (void *) (rbd + p->num_recv_buffs);
 
-   /* clr descriptors */
-  memset((char *) rbd,0,sizeof(struct rbd_struct)*p->num_recv_buffs);
+       /* clr descriptors */
+       memset((char *) rbd, 0, sizeof(struct rbd_struct) * p->num_recv_buffs);
 
-  for(i=0;i<p->num_recv_buffs;i++) {
-    rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));
-    rbd[i].size = RECV_BUFF_SIZE;
-    rbd[i].buffer = make24(ptr);
-    ptr = (char *) ptr + RECV_BUFF_SIZE;
-  }
+       for (i = 0; i < p->num_recv_buffs; i++) {
+               rbd[i].next = make16((rbd + (i + 1) % p->num_recv_buffs));
+               rbd[i].size = RECV_BUFF_SIZE;
+               rbd[i].buffer = make24(ptr);
+               ptr = (char *) ptr + RECV_BUFF_SIZE;
+       }
 
-  p->rfd_top  = p->rfd_first;
-  p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;
+       p->rfd_top = p->rfd_first;
+       p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;
 
-  p->scb->rfa_offset           = make16(p->rfd_first);
-  p->rfd_first->rbd_offset     = make16(rbd);
+       p->scb->rfa_offset = make16(p->rfd_first);
+       p->rfd_first->rbd_offset = make16(rbd);
 
-  return ptr;
+       return ptr;
 }
 
 
@@ -877,152 +868,145 @@ alloc_rfa(struct device *dev,void *ptr) {
  * Interrupt Handler ...
  */
 
-static
-void
-elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) {
-  struct device *dev = (struct device *) dev_id;
-  unsigned short stat;
-  struct priv *p;
-
-  if (dev == NULL) {
-    printk ("elmc-interrupt: irq %d for unknown device.\n",(int) -(((struct pt_regs *)reg_ptr)->orig_eax+2));
-    return;
-  } else if( !dev->start ) {
-    /* The 3c523 has this habit of generating interrupts during the
-       reset.  I'm not sure if the ni52 has this same problem, but it's
-       really annoying if we haven't finished initializing it.  I was
-       hoping all the elmc_id_* commands would disable this, but I
-       might have missed a few. */
-
-    elmc_id_attn586(); /* ack inter. and disable any more */
-    return;
-  } else if( !(ELMC_CTRL_INT & inb( dev->base_addr+ELMC_CTRL )) ) {
-       /* wasn't this device */
-       return;
-  }
-
-  /* reading ELMC_CTRL also clears the INT bit. */
-
-  p = (struct priv *) dev->priv;
-
-  dev->interrupt = 1;
-
-  while((stat=p->scb->status & STAT_MASK)) {
-    p->scb->cmd = stat;
-    elmc_attn586(); /* ack inter. */
-
-   if(stat & STAT_CX) {
-      /* command with I-bit set complete */
-      elmc_xmt_int(dev);
-   }
-
-   if(stat & STAT_FR) {
-     /* received a frame */
-     elmc_rcv_int(dev);
-   }
+static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+{
+       struct device *dev = (struct device *) dev_id;
+       unsigned short stat;
+       struct priv *p;
+
+       if (dev == NULL) {
+               printk("elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
+               return;
+       } else if (!dev->start) {
+               /* The 3c523 has this habit of generating interrupts during the
+                  reset.  I'm not sure if the ni52 has this same problem, but it's
+                  really annoying if we haven't finished initializing it.  I was
+                  hoping all the elmc_id_* commands would disable this, but I
+                  might have missed a few. */
+
+               elmc_id_attn586();      /* ack inter. and disable any more */
+               return;
+       } else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) {
+               /* wasn't this device */
+               return;
+       }
+       /* reading ELMC_CTRL also clears the INT bit. */
+
+       p = (struct priv *) dev->priv;
 
+       dev->interrupt = 1;
+
+       while ((stat = p->scb->status & STAT_MASK)) 
+       {
+               p->scb->cmd = stat;
+               elmc_attn586(); /* ack inter. */
+
+               if (stat & STAT_CX) {
+                       /* command with I-bit set complete */
+                       elmc_xmt_int(dev);
+               }
+               if (stat & STAT_FR) {
+                       /* received a frame */
+                       elmc_rcv_int(dev);
+               }
 #ifndef NO_NOPCOMMANDS
-    if(stat & STAT_CNA) {
-      /* CU went 'not ready' */
-      if(dev->start) {
-        printk("%s: oops! CU has left active state. stat: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
-         }
-    }
+               if (stat & STAT_CNA) {
+                       /* CU went 'not ready' */
+                       if (dev->start) {
+                               printk("%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+                       }
+               }
 #endif
 
-    if(stat & STAT_RNR) {
-      /* RU went 'not ready' */
-
-      if(p->scb->status & RU_SUSPEND) {
-        /* special case: RU_SUSPEND */
-
-        WAIT_4_SCB_CMD();
-        p->scb->cmd = RUC_RESUME;
-        elmc_attn586();
-      } else {
-        printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status);
-        elmc_rnr_int(dev);
-      }
-    }
-    WAIT_4_SCB_CMD(); /* wait for ack. (elmc_xmt_int can be faster than ack!!) */
-    if(p->scb->cmd) {  /* timed out? */
-      break;
-    }
-  }
-
-  dev->interrupt = 0;
+               if (stat & STAT_RNR) {
+                       /* RU went 'not ready' */
+
+                       if (p->scb->status & RU_SUSPEND) {
+                               /* special case: RU_SUSPEND */
+
+                               WAIT_4_SCB_CMD();
+                               p->scb->cmd = RUC_RESUME;
+                               elmc_attn586();
+                       } else {
+                               printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+                               elmc_rnr_int(dev);
+                       }
+               }
+               WAIT_4_SCB_CMD();       /* wait for ack. (elmc_xmt_int can be faster than ack!!) */
+               if (p->scb->cmd) {      /* timed out? */
+                       break;
+               }
+       }
+
+       dev->interrupt = 0;
 }
 
 /*******************************************************
  * receive-interrupt
  */
 
-static
-void
-elmc_rcv_int(struct device *dev) {
-  int status;
-  unsigned short totlen;
-  struct sk_buff *skb;
-  struct rbd_struct *rbd;
-  struct priv *p = (struct priv *) dev->priv;
-
-  for(;(status = p->rfd_top->status) & STAT_COMPL;) {
-      rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
-
-      if(status & STAT_OK) /* frame received without error? */
-      {
-        if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */
-        {
-          totlen &= RBD_MASK; /* length of this frame */
-          rbd->status = 0;
-          skb = (struct sk_buff *) dev_alloc_skb(totlen+2);
-          if(skb != NULL) {
-             skb->dev = dev;
-            skb_reserve(skb,2);                /* 16 byte alignment */
-            memcpy(skb_put(skb,totlen),(char *) p->base+(unsigned long) rbd->buffer, totlen);
-            skb->protocol=eth_type_trans(skb,dev);
-            netif_rx(skb);
-            p->stats.rx_packets++;
-            p->stats.rx_bytes+=totlen;
-          } else {
-            p->stats.rx_dropped++;
-                 }
-        } else {
-          printk("%s: received oversized frame.\n",dev->name);
-          p->stats.rx_dropped++;
-        }
-      } else /* frame !(ok), only with 'save-bad-frames' */ {
-        printk("%s: oops! rfd-error-status: %04x\n",dev->name,status);
-        p->stats.rx_errors++;
-      }
-      p->rfd_top->status = 0;
-      p->rfd_top->last = RFD_SUSP;
-      p->rfd_last->last = 0;        /* delete RU_SUSP  */
-      p->rfd_last = p->rfd_top;
-      p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
-  }
+static void elmc_rcv_int(struct device *dev)
+{
+       int status;
+       unsigned short totlen;
+       struct sk_buff *skb;
+       struct rbd_struct *rbd;
+       struct priv *p = (struct priv *) dev->priv;
+
+       for (; (status = p->rfd_top->status) & STAT_COMPL;) {
+               rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
+
+               if (status & STAT_OK) {         /* frame received without error? */
+                       if ((totlen = rbd->status) & RBD_LAST) {        /* the first and the last buffer? */
+                               totlen &= RBD_MASK;     /* length of this frame */
+                               rbd->status = 0;
+                               skb = (struct sk_buff *) dev_alloc_skb(totlen + 2);
+                               if (skb != NULL) {
+                                       skb->dev = dev;
+                                       skb_reserve(skb, 2);    /* 16 byte alignment */
+                                       memcpy(skb_put(skb, totlen), (char *) p->base + (unsigned long) rbd->buffer, totlen);
+                                       skb->protocol = eth_type_trans(skb, dev);
+                                       netif_rx(skb);
+                                       p->stats.rx_packets++;
+                                       p->stats.rx_bytes += totlen;
+                               } else {
+                                       p->stats.rx_dropped++;
+                               }
+                       } else {
+                               printk("%s: received oversized frame.\n", dev->name);
+                               p->stats.rx_dropped++;
+                       }
+               } else {        /* frame !(ok), only with 'save-bad-frames' */
+                       printk("%s: oops! rfd-error-status: %04x\n", dev->name, status);
+                       p->stats.rx_errors++;
+               }
+               p->rfd_top->status = 0;
+               p->rfd_top->last = RFD_SUSP;
+               p->rfd_last->last = 0;  /* delete RU_SUSP  */
+               p->rfd_last = p->rfd_top;
+               p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next);    /* step to next RFD */
+       }
 }
 
 /**********************************************************
  * handle 'Receiver went not ready'.
  */
 
-static
-void
-elmc_rnr_int(struct device *dev) {
-  struct priv *p = (struct priv *) dev->priv;
+static void elmc_rnr_int(struct device *dev)
+{
+       struct priv *p = (struct priv *) dev->priv;
 
-  p->stats.rx_errors++;
+       p->stats.rx_errors++;
 
-  WAIT_4_SCB_CMD();    /* wait for the last cmd */
-  p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */
-  elmc_attn586();
-  WAIT_4_SCB_CMD();    /* wait for accept cmd. */
+       WAIT_4_SCB_CMD();       /* wait for the last cmd */
+       p->scb->cmd = RUC_ABORT;        /* usually the RU is in the 'no resource'-state .. abort it now. */
+       elmc_attn586();
+       WAIT_4_SCB_CMD();       /* wait for accept cmd. */
 
-  alloc_rfa(dev,(char *)p->rfd_first);
-  startrecv586(dev); /* restart RU */
+       alloc_rfa(dev, (char *) p->rfd_first);
+       startrecv586(dev);      /* restart RU */
 
-  printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->status);
+       printk("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
 
 }
 
@@ -1030,286 +1014,269 @@ elmc_rnr_int(struct device *dev) {
  * handle xmit - interrupt
  */
 
-static
-void
-elmc_xmt_int(struct device *dev) {
-  int status;
-  struct priv *p = (struct priv *) dev->priv;
-
-  status = p->xmit_cmds[p->xmit_last]->cmd_status;
-  if(!(status & STAT_COMPL)) {
-    printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name);
-  }
-
-  if(status & STAT_OK) {
-    p->stats.tx_packets++;
-    p->stats.collisions += (status & TCMD_MAXCOLLMASK);
-  } else {
-    p->stats.tx_errors++;
-    if(status & TCMD_LATECOLL) {
-      printk("%s: late collision detected.\n",dev->name);
-      p->stats.collisions++;
-    } else if(status & TCMD_NOCARRIER) {
-      p->stats.tx_carrier_errors++;
-      printk("%s: no carrier detected.\n",dev->name);
-    } else if(status & TCMD_LOSTCTS) {
-      printk("%s: loss of CTS detected.\n",dev->name);
-    } else if(status & TCMD_UNDERRUN) {
-      p->stats.tx_fifo_errors++;
-      printk("%s: DMA underrun detected.\n",dev->name);
-    } else if(status & TCMD_MAXCOLL) {
-      printk("%s: Max. collisions exceeded.\n",dev->name);
-      p->stats.collisions += 16;
-    }
-  }
+static void elmc_xmt_int(struct device *dev)
+{
+       int status;
+       struct priv *p = (struct priv *) dev->priv;
+
+       status = p->xmit_cmds[p->xmit_last]->cmd_status;
+       if (!(status & STAT_COMPL)) {
+               printk("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
+       }
+       if (status & STAT_OK) {
+               p->stats.tx_packets++;
+               p->stats.collisions += (status & TCMD_MAXCOLLMASK);
+       } else {
+               p->stats.tx_errors++;
+               if (status & TCMD_LATECOLL) {
+                       printk("%s: late collision detected.\n", dev->name);
+                       p->stats.collisions++;
+               } else if (status & TCMD_NOCARRIER) {
+                       p->stats.tx_carrier_errors++;
+                       printk("%s: no carrier detected.\n", dev->name);
+               } else if (status & TCMD_LOSTCTS) {
+                       printk("%s: loss of CTS detected.\n", dev->name);
+               } else if (status & TCMD_UNDERRUN) {
+                       p->stats.tx_fifo_errors++;
+                       printk("%s: DMA underrun detected.\n", dev->name);
+               } else if (status & TCMD_MAXCOLL) {
+                       printk("%s: Max. collisions exceeded.\n", dev->name);
+                       p->stats.collisions += 16;
+               }
+       }
 
 #if (NUM_XMIT_BUFFS != 1)
-  if( (++p->xmit_last) == NUM_XMIT_BUFFS) {
-    p->xmit_last = 0;
-  }
+       if ((++p->xmit_last) == NUM_XMIT_BUFFS) {
+               p->xmit_last = 0;
+       }
 #endif
 
-  dev->tbusy = 0;
-  mark_bh(NET_BH);
+       dev->tbusy = 0;
+       mark_bh(NET_BH);
 }
 
 /***********************************************************
  * (re)start the receiver
  */
 
-static
-void
-startrecv586(struct device *dev)
+static void startrecv586(struct device *dev)
 {
-  struct priv *p = (struct priv *) dev->priv;
+       struct priv *p = (struct priv *) dev->priv;
 
-  p->scb->rfa_offset = make16(p->rfd_first);
-  p->scb->cmd = RUC_START;
-  elmc_attn586();              /* start cmd. */
-  WAIT_4_SCB_CMD();    /* wait for accept cmd. (no timeout!!) */
+       p->scb->rfa_offset = make16(p->rfd_first);
+       p->scb->cmd = RUC_START;
+       elmc_attn586();         /* start cmd. */
+       WAIT_4_SCB_CMD();       /* wait for accept cmd. (no timeout!!) */
 }
 
 /******************************************************
  * send frame
  */
 
-static
-int
-elmc_send_packet(struct sk_buff *skb, struct device *dev)
+static int elmc_send_packet(struct sk_buff *skb, struct device *dev)
 {
-  int len;
+       int len;
 #ifndef NO_NOPCOMMANDS
-  int next_nop;
+       int next_nop;
 #endif
-  struct priv *p = (struct priv *) dev->priv;
-
-  if(dev->tbusy) {
-    int tickssofar = jiffies - dev->trans_start;
-    if (tickssofar < 5) {
-      return 1;
-    }
+       struct priv *p = (struct priv *) dev->priv;
 
-    /* COMMAND-UNIT active? */
-    if(p->scb->status & CU_ACTIVE) {
-      dev->tbusy = 0;
+       if (dev->tbusy) {
+               int tickssofar = jiffies - dev->trans_start;
+               if (tickssofar < 5) {
+                       return 1;
+               }
+               /* COMMAND-UNIT active? */
+               if (p->scb->status & CU_ACTIVE) {
+                       dev->tbusy = 0;
 #ifdef DEBUG
-      printk("%s: strange ... timeout with CU active?!?\n",dev->name);
-      printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
+                       printk("%s: strange ... timeout with CU active?!?\n", dev->name);
+                       printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);
 #endif
-      p->scb->cmd = CUC_ABORT;
-      elmc_attn586();
-      WAIT_4_SCB_CMD();
-      p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
-      p->scb->cmd = CUC_START;
-      elmc_attn586();
-      WAIT_4_SCB_CMD();
-      dev->trans_start = jiffies;
-      return 0;
-    } else {
+                       p->scb->cmd = CUC_ABORT;
+                       elmc_attn586();
+                       WAIT_4_SCB_CMD();
+                       p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
+                       p->scb->cmd = CUC_START;
+                       elmc_attn586();
+                       WAIT_4_SCB_CMD();
+                       dev->trans_start = jiffies;
+                       return 0;
+               } else {
 #ifdef DEBUG
-      printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status);
-      printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
+                       printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);
+                       printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
 #endif
-      elmc_close(dev);
-      elmc_open(dev);
-    }
-    dev->trans_start = jiffies;
-    return 0;
-  }
-
-  if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-     printk("%s: Transmitter access conflict.\n", dev->name);
-  } else {
-    memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
-    len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+                       elmc_close(dev);
+                       elmc_open(dev);
+               }
+               dev->trans_start = jiffies;
+               return 0;
+       }
+       if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+               printk("%s: Transmitter access conflict.\n", dev->name);
+       } else {
+               memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
+               len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 
 #if (NUM_XMIT_BUFFS == 1)
-#  ifdef NO_NOPCOMMANDS
-    p->xmit_buffs[0]->size = TBD_LAST | len;
-    for(i=0;i<16;i++) {
-      p->scb->cbl_offset = make16(p->xmit_cmds[0]);
-      p->scb->cmd = CUC_START;
-      p->xmit_cmds[0]->cmd_status = 0;
-
-      elmc_attn586();
-      dev->trans_start = jiffies;
-      if(!i) {
-        dev_kfree_skb(skb);
-         }
-      WAIT_4_SCB_CMD();
-      if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */
-      {
-        break;
-      }
-      if(p->xmit_cmds[0]->cmd_status) {
-        break;
-         }
-      if(i==15) {
-        printk("%s: Can't start transmit-command.\n",dev->name);
-         }
-    }
-#  else
-    next_nop = (p->nop_point + 1) & 0x1;
-    p->xmit_buffs[0]->size = TBD_LAST | len;
-
-    p->xmit_cmds[0]->cmd_link   = p->nop_cmds[next_nop]->cmd_link
-                                = make16((p->nop_cmds[next_nop]));
-    p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
-
-    p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
-    dev->trans_start = jiffies;
-    p->nop_point = next_nop;
-    dev_kfree_skb(skb);
-#  endif
+#ifdef NO_NOPCOMMANDS
+               p->xmit_buffs[0]->size = TBD_LAST | len;
+               for (i = 0; i < 16; i++) {
+                       p->scb->cbl_offset = make16(p->xmit_cmds[0]);
+                       p->scb->cmd = CUC_START;
+                       p->xmit_cmds[0]->cmd_status = 0;
+
+                       elmc_attn586();
+                       dev->trans_start = jiffies;
+                       if (!i) {
+                               dev_kfree_skb(skb);
+                       }
+                       WAIT_4_SCB_CMD();
+                       if ((p->scb->status & CU_ACTIVE)) {     /* test it, because CU sometimes doesn't start immediately */
+                               break;
+                       }
+                       if (p->xmit_cmds[0]->cmd_status) {
+                               break;
+                       }
+                       if (i == 15) {
+                               printk("%s: Can't start transmit-command.\n", dev->name);
+                       }
+               }
 #else
-    p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
-    if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) {
-      next_nop = 0;
-    }
-
-    p->xmit_cmds[p->xmit_count]->cmd_status  = 0;
-    p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
-                                          = make16((p->nop_cmds[next_nop]));
-    p->nop_cmds[next_nop]->cmd_status = 0;
-
-    p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
-    dev->trans_start = jiffies;
-    p->xmit_count = next_nop;
-
-    cli();
-    if(p->xmit_count != p->xmit_last) {
-      dev->tbusy = 0;
-    }
-    sti();
-    dev_kfree_skb(skb);
+               next_nop = (p->nop_point + 1) & 0x1;
+               p->xmit_buffs[0]->size = TBD_LAST | len;
+
+               p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
+                   = make16((p->nop_cmds[next_nop]));
+               p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
+
+               p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
+               dev->trans_start = jiffies;
+               p->nop_point = next_nop;
+               dev_kfree_skb(skb);
 #endif
-  }
-  return 0;
+#else
+               p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
+               if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
+                       next_nop = 0;
+               }
+               p->xmit_cmds[p->xmit_count]->cmd_status = 0;
+               p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
+                   = make16((p->nop_cmds[next_nop]));
+               p->nop_cmds[next_nop]->cmd_status = 0;
+
+               p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
+               dev->trans_start = jiffies;
+               p->xmit_count = next_nop;
+
+               cli();
+               if (p->xmit_count != p->xmit_last) {
+                       dev->tbusy = 0;
+               }
+               sti();
+               dev_kfree_skb(skb);
+#endif
+       }
+       return 0;
 }
 
 /*******************************************
  * Someone wanna have the statistics
  */
 
-static struct net_device_stats *elmc_get_stats( struct device *dev ) 
+static struct net_device_stats *elmc_get_stats(struct device *dev)
 {
-  struct priv *p = (struct priv *) dev->priv;
-  unsigned short crc,aln,rsc,ovrn;
-
-  crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
-  p->scb->crc_errs -= crc;
-  aln = p->scb->aln_errs;
-  p->scb->aln_errs -= aln;
-  rsc = p->scb->rsc_errs;
-  p->scb->rsc_errs -= rsc;
-  ovrn = p->scb->ovrn_errs;
-  p->scb->ovrn_errs -= ovrn;
-
-  p->stats.rx_crc_errors += crc;
-  p->stats.rx_fifo_errors += ovrn;
-  p->stats.rx_frame_errors += aln;
-  p->stats.rx_dropped += rsc;
-
-  return &p->stats;
+       struct priv *p = (struct priv *) dev->priv;
+       unsigned short crc, aln, rsc, ovrn;
+
+       crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
+       p->scb->crc_errs -= crc;
+       aln = p->scb->aln_errs;
+       p->scb->aln_errs -= aln;
+       rsc = p->scb->rsc_errs;
+       p->scb->rsc_errs -= rsc;
+       ovrn = p->scb->ovrn_errs;
+       p->scb->ovrn_errs -= ovrn;
+
+       p->stats.rx_crc_errors += crc;
+       p->stats.rx_fifo_errors += ovrn;
+       p->stats.rx_frame_errors += aln;
+       p->stats.rx_dropped += rsc;
+
+       return &p->stats;
 }
 
 /********************************************************
  * Set MC list ..
  */
 
-static
-void
-set_multicast_list(struct device *dev) {
-  if(!dev->start) {
-    /* without a running interface, promiscuous doesn't work */
-    return;
-  }
-
-  dev->start = 0;
-  alloc586(dev);
-  init586(dev);
-  startrecv586(dev);
-  dev->start = 1;
+static void set_multicast_list(struct device *dev)
+{
+       if (!dev->start) {
+               /* without a running interface, promiscuous doesn't work */
+               return;
+       }
+       dev->start = 0;
+       alloc586(dev);
+       init586(dev);
+       startrecv586(dev);
+       dev->start = 1;
 }
 
 /*************************************************************************/
 
 #ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_elmc = {
-       devicename /*"3c523"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe };
 
-static int irq=0;
-static int io=0;
+static char devicename[9] = {0,};
+
+static struct device dev_elmc =
+{
+       devicename /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe
+};
+
+static int irq = 0;
+static int io = 0;
 MODULE_PARM(irq, "i");
 MODULE_PARM(io, "i");
 
-int
-init_module(void) {
+int init_module(void)
+{
        struct device *dev = &dev_elmc;
 
-       dev->base_addr=io;
-       dev->irq=irq;
+       dev->base_addr = io;
+       dev->irq = irq;
        if (register_netdev(dev) != 0) {
                return -EIO;
        }
-
        return 0;
 }
 
-void
-cleanup_module(void) {
+void cleanup_module(void)
+{
        struct device *dev = &dev_elmc;
 
-       if (MOD_IN_USE) {
-               printk("3c523: device busy, remove delayed\n");
-       } else {
-               /* shutdown interrupts on the card */
-               elmc_id_reset586();
-
-               if( dev->irq != 0 ) {
-             /* this should be done by close, but if we failed to
-             initialize properly something may have gotten hosed. */
-             free_irq( dev->irq, dev );
-             dev->irq = 0;
-           }
-
-
-
-               if( dev->base_addr != 0 ) {
-                 release_region( dev->base_addr, ELMC_IO_EXTENT );
-                 dev->base_addr = 0;
-               }
-               irq = 0;
-               io = 0;
-
-               unregister_netdev(dev);
+       /* shutdown interrupts on the card */
+       elmc_id_reset586();
+       if (dev->irq != 0) {
+               /* this should be done by close, but if we failed to
+                  initialize properly something may have gotten hosed. */
+               free_irq(dev->irq, dev);
+               dev->irq = 0;
+       }
+       if (dev->base_addr != 0) {
+               release_region(dev->base_addr, ELMC_IO_EXTENT);
+               dev->base_addr = 0;
+       }
+       irq = 0;
+       io = 0;
+       unregister_netdev(dev);
 
-               mca_set_adapter_procfn( ((struct priv *) (dev->priv))->slot,
-                       NULL, NULL );
+       mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot,
+                              NULL, NULL);
 
-               kfree_s(dev->priv,sizeof(struct priv));
-               dev->priv=NULL;
-       }
+       kfree_s(dev->priv, sizeof(struct priv));
+       dev->priv = NULL;
 }
-#endif /* MODULE */
+
+#endif                         /* MODULE */
index 889229892ab6ade92a6333536898e01558c1ca50..1711de5dcfa60629942fd4b2cf6c497f2cdbc24d 100644 (file)
@@ -79,6 +79,8 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
 #include <linux/pci.h>
 #include <linux/bios32.h>
 #include <linux/timer.h>
+
+#include <asm/byteorder.h>
 #include <asm/irq.h>                   /* For NR_IRQS only. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -332,10 +334,20 @@ enum Window3 {                    /* Window 3: MAC/config bits. */
 union wn3_config {
        int i;
        struct w3_config_fields {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
                unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
                int pad8:8;
                unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
                int pad24:7;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+               unsigned int rom_size:2, ram_speed:2, ram_width:1, ram_size:3;
+               int pad8:8;
+               unsigned int xcvr:4, pad18:2, ram_split:2;
+               int pad24:7;
+               unsigned int autoselect:1;
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
        } u;
 };
 
index 1c558f51b8ccd71666edb0eef812fbeeade670d5..9aca8d0b6c4aa57dc9783c87b875f09933bced42 100644 (file)
@@ -56,6 +56,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       fi
     fi
     tristate '3c509/3c579 support' CONFIG_EL3
+    tristate '3c515 ISA Fast EtherLink' CONFIG_3C515
     tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
   fi
   bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
@@ -84,7 +85,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
   bool 'Other ISA cards' CONFIG_NET_ISA
   if [ "$CONFIG_NET_ISA" = "y" ]; then
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'AT1700 support (EXPERIMENTAL)' CONFIG_AT1700
+      tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
     fi
     tristate 'Cabletron E21xx support' CONFIG_E2100
     tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
index 343c86eb099f340ce1f9903de2197cbdb6e944bb..3e8fcda06b4eab0b8d89e5712fe0bf5c728da22b 100644 (file)
@@ -482,6 +482,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_3C515),y)
+L_OBJS += 3c515.o
+else
+  ifeq ($(CONFIG_3C515),m)
+  M_OBJS += 3c515.o
+  endif
+endif
+
 ifeq ($(CONFIG_VORTEX),y)
 L_OBJS += 3c59x.o
 else
index 6d1b78468d10178e25e451e27dbe80b117341d10..6007d235ed2d6de6066c94bd66da6a5fa2a78e8c 100644 (file)
@@ -110,6 +110,7 @@ extern int epic100_probe(struct device *dev);
 extern int rtl8139_probe(struct device *dev);
 extern int hplance_probe(struct device *dev);
 extern int via_rhine_probe(struct device *dev);
+extern int tc515_probe(struct device *dev);
 
 /* Gigabit Ethernet adapters */
 extern int yellowfin_probe(struct device *dev);
@@ -268,6 +269,9 @@ struct devprobe isa_probes[] __initdata = {
 #ifdef CONFIG_HP100            /* ISA, EISA & PCI */
        {hp100_probe, 0},
 #endif 
+#ifdef CONFIG_3C515
+       {tc515_probe, 0},
+#endif
 #ifdef CONFIG_ULTRA 
        {ultra_probe, 0},
 #endif
index 5e6fb215b48d0996c38d10c204655c1fc7ceb2ab..0b71b5987088e6c8c9f136ba62ff9f99e25afaad 100644 (file)
@@ -97,7 +97,7 @@ __initfunc(int ariadne2_probe(struct device *dev))
            return 0;
        }
     }
-    return ENODEV;
+    return -ENODEV;
 }
 
 __initfunc(static int ariadne2_init(struct device *dev, unsigned int key,
@@ -131,7 +131,7 @@ __initfunc(static int ariadne2_init(struct device *dev, unsigned int key,
        while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
            if (jiffies - reset_start_time > 2*HZ/100) {
                printk(" not found (no reset ack).\n");
-               return ENODEV;
+               return -ENODEV;
            }
 
        writeb(0xff, ioaddr + NE_EN0_ISR);              /* Ack all intr. */
index 3751b43368bd714415d4a785a335585edc3fe1d9..9e9cf4a42a7f97f78b6c526280a8e8edc8ec4a39 100644 (file)
@@ -1,6 +1,6 @@
 /* at1700.c: A network device driver for  the Allied Telesis AT1700.
 
-       Written 1993-94 by Donald Becker.
+       Written 1993-98 by Donald Becker.
 
        Copyright 1993 United States Government as represented by the
        Director, National Security Agency.
@@ -22,6 +22,8 @@
        ATI provided their EEPROM configuration code header file.
     Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
 
+    MCA bus (AT1720) support by Rene Schmit <rene@bss.lu>
+
   Bugs:
        The MB86965 has a design flaw that makes all probes unreliable.  Not
        only is it difficult to detect, it also moves around in I/O space in
@@ -29,7 +31,7 @@
 */
 
 static const char *version =
-       "at1700.c:v1.12 1/18/95  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+       "at1700.c:v1.15 4/7/98  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include <linux/module.h>
 
@@ -48,15 +50,48 @@ static const char *version =
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
-#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-/* This unusual address order is used to verify the CONFIG register. */
-static int at1700_probe_list[] __initdata =
-{0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0};
+#include <linux/mca.h>
+
+/* Tunable parameters. */
+
+/* When to switch from the 64-entry multicast filter to Rx-all-multicast. */
+#define MC_FILTERBREAK 64
+
+/* These unusual address orders are used to verify the CONFIG register. */
+
+static int fmv18x_probe_list[] = {
+       0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
+};
+
+/*
+ *     ISA
+ */
+
+static int at1700_probe_list[] = {
+       0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
+};
+
+/*
+ *     MCA
+ */
+
+static int at1700_ioaddr_pattern[] = {
+       0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
+};
+
+static int at1700_mca_probe_list[] = {
+       0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0
+};
+
+static int at1700_irq_pattern[] = {
+       0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
+       0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
+};
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
@@ -68,10 +103,14 @@ typedef unsigned char uchar;
 
 /* Information that need to be kept for each board. */
 struct net_local {
-       struct net_device_stats stats;
-       uint tx_started:1;                      /* Number of packet on the Tx queue. */
+       struct enet_statistics stats;
+       unsigned char mc_filter[8];
+       uint jumpered:1;                        /* Set iff the board has jumper config. */
+       uint tx_started:1;                      /* Packets are on the Tx queue. */
+       uint invalid_irq:1;
        uchar tx_queue;                         /* Number of packet on the Tx queue. */
-       ushort tx_queue_len;            /* Current length of the Tx queue. */
+       char mca_slot;                          /* -1 means ISA */
+       ushort tx_queue_len;                    /* Current length of the Tx queue. */
 };
 
 
@@ -89,56 +128,59 @@ struct net_local {
 #define DATAPORT               8               /* Word-wide DMA or programmed-I/O dataport. */
 #define TX_START               10
 #define MODE13                 13
+/* Configuration registers only on the '865A/B chips. */
 #define EEPROM_Ctrl    16
 #define EEPROM_Data    17
-#define IOCONFIG               19
+#define IOCONFIG               18              /* Either read the jumper, or move the I/O. */
+#define IOCONFIG1              19
+#define        SAPROM                  20              /* The station address PROM, if no EEPROM. */
 #define RESET                  31              /* Write to reset some parts of the chip. */
 #define AT1700_IO_EXTENT       32
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK   0x40    /* EEPROM shift clock, in reg. 16. */
-#define EE_CS                  0x20    /* EEPROM chip select, in reg. 16. */
-#define EE_DATA_WRITE  0x80    /* EEPROM chip data in, in reg. 17. */
-#define EE_DATA_READ   0x80    /* EEPROM chip data out, in reg. 17. */
-
-/* Delay between EEPROM clock transitions. */
-#define eeprom_delay() do { int _i = 40; while (--_i > 0) { inb(0x80); }} while (0)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD   (5 << 6)
-#define EE_READ_CMD            (6 << 6)
-#define EE_ERASE_CMD   (7 << 6)
-
-
 /* Index to functions, as function prototypes. */
 
 extern int at1700_probe(struct device *dev);
 
-static int at1700_probe1(struct device *dev, short ioaddr);
+static int at1700_probe1(struct device *dev, int ioaddr);
 static int read_eeprom(int ioaddr, int location);
 static int net_open(struct device *dev);
 static int     net_send_packet(struct sk_buff *skb, struct device *dev);
 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void net_rx(struct device *dev);
 static int net_close(struct device *dev);
-static struct net_device_stats *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static struct enet_statistics *net_get_stats(struct device *dev);
+static void set_rx_mode(struct device *dev);
 
 \f
+#ifdef CONFIG_MCA
+struct at1720_mca_adapters_struct {
+       char* name;
+       int id;
+};
+/* rEnE : maybe there are others I don't know off... */
+
+struct at1720_mca_adapters_struct at1720_mca_adapters[] = {
+       { "Allied Telesys AT1720AT",    0x6410 },
+       { "Allied Telesys AT1720BT",    0x6413 },
+       { "Allied Telesys AT1720T",             0x6416 },
+       { NULL, 0 },
+};
+#endif
+
 /* Check for a network adaptor of this type, and return '0' iff one exists.
    If dev->base_addr == 0, probe all likely locations.
    If dev->base_addr == 1, always return failure.
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
    */
+
 #ifdef HAVE_DEVLIST
-/* Support for an alternate probe manager, which will eliminate the
+/* Support for a alternate probe manager, which will eliminate the
    boilerplate below. */
 struct netdev_entry at1700_drv =
 {"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list};
 #else
-__initfunc(int
-at1700_probe(struct device *dev))
+
+int at1700_probe(struct device *dev)
 {
        int i;
        int base_addr = dev ? dev->base_addr : 0;
@@ -155,7 +197,6 @@ at1700_probe(struct device *dev))
                if (at1700_probe1(dev, ioaddr) == 0)
                        return 0;
        }
-
        return ENODEV;
 }
 #endif
@@ -168,12 +209,15 @@ at1700_probe(struct device *dev))
    that can be done is checking a few bits and then diving right into an
    EEPROM read. */
 
-__initfunc(int at1700_probe1(struct device *dev, short ioaddr))
+int at1700_probe1(struct device *dev, int ioaddr)
 {
-       char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
-       unsigned int i, irq;
-
-       /* Resetting the chip doesn't reset the ISA interface, so don't bother.
+       char fmv_irqmap[4] = {3, 7, 10, 15};
+       char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
+       unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
+       int l_i;
+       int slot;
+       
+               /* Resetting the chip doesn't reset the ISA interface, so don't bother.
           That means we have to be careful with the register values we probe for.
           */
 #ifdef notdef
@@ -181,31 +225,98 @@ __initfunc(int at1700_probe1(struct device *dev, short ioaddr))
                   ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
                   read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
 #endif
-       if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr
-               || read_eeprom(ioaddr, 4) != 0x0000
-               || (read_eeprom(ioaddr, 5) & 0xff00) != 0xF400)
+
+#ifdef CONFIG_MCA
+       /* rEnE (rene@bss.lu): got this from 3c509 driver source , adapted for AT1720 */
+
+    /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
+       modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
+       to support standard MCA probing. */
+
+       /* redone for multi-card detection by ZP Gu (zpg@castle.net) */
+       /* now works as a module */
+
+       if( MCA_bus ) {
+               int j;
+               u_char pos3, pos4;
+
+               for( j = 0; at1720_mca_adapters[j].name != NULL; j ++ ) {
+                       slot = 0;
+                       while( slot != MCA_NOTFOUND ) {
+                               
+                               slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
+                               if( slot == MCA_NOTFOUND ) break;
+
+                               /* if we get this far, an adapter has been detected and is
+                               enabled */
+
+                               pos3 = mca_read_stored_pos( slot, 3 );
+                               pos4 = mca_read_stored_pos( slot, 4 );
+
+                               for (l_i = 0; l_i < 0x09; l_i++)
+                                       if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
+                                               break;
+                               ioaddr = at1700_mca_probe_list[l_i];
+                               
+                               for (irq = 0; irq < 0x10; irq++)
+                                       if (((((pos4>>4) & 0x0f) | (pos3 & 0xf0)) & 0xff) == at1700_irq_pattern[irq])
+                                               break;
+
+                                       /* probing for a card at a particular IO/IRQ */
+                               if (dev &&
+                                       ((dev->irq && dev->irq != irq) ||
+                                        (dev->base_addr && dev->base_addr != ioaddr))) {
+                                       slot++;         /* probing next slot */
+                                       continue;
+                               }
+
+                               if (dev)
+                                       dev->irq = irq;
+                               
+                               /* claim the slot */
+                               mca_set_adapter_name( slot, at1720_mca_adapters[j].name );
+                               mca_mark_as_used(slot);
+
+                               goto found;
+                       }
+               }
+               /* if we get here, we didn't find an MCA adapter - try ISA */
+       }
+#endif
+       slot = -1;
+       /* We must check for the EEPROM-config boards first, else accessing
+          IOCONFIG0 will move the board! */
+       if (at1700_probe_list[inb(ioaddr + IOCONFIG1) & 0x07] == ioaddr
+               && read_eeprom(ioaddr, 4) == 0x0000
+               && (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400)
+               is_at1700 = 1;
+       else if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] == ioaddr
+               && inb(ioaddr + SAPROM    ) == 0x00
+               && inb(ioaddr + SAPROM + 1) == 0x00
+               && inb(ioaddr + SAPROM + 2) == 0x0e)
+               is_fmv18x = 1;
+       else
                return -ENODEV;
+                       
+found:
 
-       /* Reset the internal state machines. */
+               /* Reset the internal state machines. */
        outb(0, ioaddr + RESET);
 
-       irq = irqmap[(read_eeprom(ioaddr, 12)&0x04)
-                                | (read_eeprom(ioaddr, 0)>>14)];
-
-       /* Snarf the interrupt vector now. */
-       if (request_irq(irq, &net_interrupt, 0, "at1700", dev)) {
-               printk ("AT1700 found at %#3x, but it's unusable due to a conflict on"
-                               "IRQ %d.\n", ioaddr, irq);
-               return EAGAIN;
-       }
-
        /* Allocate a new 'dev' if needed. */
        if (dev == NULL)
                dev = init_etherdev(0, sizeof(struct net_local));
 
+       if (is_at1700)
+               irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
+                                                  | (read_eeprom(ioaddr, 0)>>14)];
+       else
+               if (is_fmv18x)
+                       irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
+       
        /* Grab the region so that we can find another board if the IRQ request
           fails. */
-       request_region(ioaddr, AT1700_IO_EXTENT, "at1700");
+       request_region(ioaddr, AT1700_IO_EXTENT, dev->name);
 
        printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
                   ioaddr, irq);
@@ -234,12 +345,12 @@ __initfunc(int at1700_probe1(struct device *dev, short ioaddr))
        }
 
        /* Set the station address in bank zero. */
-       outb(0xe0, ioaddr + 7);
+       outb(0xe0, ioaddr + CONFIG_1);
        for (i = 0; i < 6; i++)
                outb(dev->dev_addr[i], ioaddr + 8 + i);
 
        /* Switch to bank 1 and set the multicast table to accept none. */
-       outb(0xe4, ioaddr + 7);
+       outb(0xe4, ioaddr + CONFIG_1);
        for (i = 0; i < 8; i++)
                outb(0x00, ioaddr + 8 + i);
 
@@ -248,7 +359,7 @@ __initfunc(int at1700_probe1(struct device *dev, short ioaddr))
        outb(0xda, ioaddr + CONFIG_0);
 
        /* Switch to bank 2 and lock our I/O address. */
-       outb(0xe8, ioaddr + 7);
+       outb(0xe8, ioaddr + CONFIG_1);
        outb(dev->if_port, MODE13);
 
        /* Power-down the chip.  Aren't we green! */
@@ -265,52 +376,75 @@ __initfunc(int at1700_probe1(struct device *dev, short ioaddr))
 
        dev->open               = net_open;
        dev->stop               = net_close;
-       dev->hard_start_xmit    = net_send_packet;
-       dev->get_stats          = net_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
+       dev->hard_start_xmit = net_send_packet;
+       dev->get_stats  = net_get_stats;
+       dev->set_multicast_list = &set_rx_mode;
 
        /* Fill in the fields of 'dev' with ethernet-generic values. */
-
        ether_setup(dev);
+
+       {
+               struct net_local *lp = (struct net_local *)dev->priv;
+               lp->jumpered = is_fmv18x;
+               lp->mca_slot = slot;
+               /* Snarf the interrupt vector now. */
+               if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) {
+                       printk ("  AT1700 at %#3x is unusable due to a conflict on"
+                                       "IRQ %d.\n", ioaddr, irq);
+                       lp->invalid_irq = 1;
+                       return 0;
+               }
+       }
+
        return 0;
 }
 
-__initfunc(static int read_eeprom(int ioaddr, int location))
+\f
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK   0x40    /* EEPROM shift clock, in reg. 16. */
+#define EE_CS                  0x20    /* EEPROM chip select, in reg. 16. */
+#define EE_DATA_WRITE  0x80    /* EEPROM chip data in, in reg. 17. */
+#define EE_DATA_READ   0x80    /* EEPROM chip data out, in reg. 17. */
+
+/* Delay between EEPROM clock transitions. */
+#define eeprom_delay() do {} while (0);
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD   (5 << 6)
+#define EE_READ_CMD            (6 << 6)
+#define EE_ERASE_CMD   (7 << 6)
+
+static int read_eeprom(int ioaddr, int location)
 {
        int i;
        unsigned short retval = 0;
-       short ee_addr = ioaddr + EEPROM_Ctrl;
-       short ee_daddr = ioaddr + EEPROM_Data;
+       int ee_addr = ioaddr + EEPROM_Ctrl;
+       int ee_daddr = ioaddr + EEPROM_Data;
        int read_cmd = location | EE_READ_CMD;
-       short ctrl_val = EE_CS;
-
-       outb(ctrl_val, ee_addr);
 
        /* Shift the read command bits out. */
        for (i = 9; i >= 0; i--) {
                short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               outb(EE_CS, ee_addr);
                outb(dataval, ee_daddr);
-               outb(EE_CS | EE_SHIFT_CLK, ee_addr);    /* EEPROM clock tick. */
                eeprom_delay();
-               outb(EE_CS, ee_addr);   /* Finish EEPROM a clock tick. */
+               outb(EE_CS | EE_SHIFT_CLK, ee_addr);    /* EEPROM clock tick. */
                eeprom_delay();
        }
-       outb(EE_CS, ee_addr);
-
+       outb(EE_DATA_WRITE, ee_daddr);
        for (i = 16; i > 0; i--) {
+               outb(EE_CS, ee_addr);
+               eeprom_delay();
                outb(EE_CS | EE_SHIFT_CLK, ee_addr);
                eeprom_delay();
                retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0);
-               outb(EE_CS, ee_addr);
-               eeprom_delay();
        }
 
        /* Terminate the EEPROM access. */
-       ctrl_val &= ~EE_CS;
-       outb(ctrl_val | EE_SHIFT_CLK, ee_addr);
-       eeprom_delay();
-       outb(ctrl_val, ee_addr);
+       outb(EE_CS, ee_addr);
        eeprom_delay();
+       outb(EE_SHIFT_CLK, ee_addr);
+       outb(0, ee_addr);
        return retval;
 }
 
@@ -330,7 +464,7 @@ static int net_open(struct device *dev)
                outb(dev->dev_addr[i], ioaddr + 8 + i);
 
        /* Switch to bank 1 and set the multicast table to accept none. */
-       outb(0xe4, ioaddr + 7);
+       outb(0xe4, ioaddr + CONFIG_1);
        for (i = 0; i < 8; i++)
                outb(0x00, ioaddr + 8 + i);
 
@@ -338,10 +472,8 @@ static int net_open(struct device *dev)
           bus access, and two 4K Tx queues. */
        outb(0xda, ioaddr + CONFIG_0);
 
-       /* Same config 0, except enable the Rx and Tx. */
-       outb(0x5a, ioaddr + CONFIG_0);
-       /* Switch to register bank 2 for the run-time registers. */
-       outb(0xe8, ioaddr + CONFIG_1);
+       /* Switch to register bank 2, enable the Rx and Tx. */
+       outw(0xe85a, ioaddr + CONFIG_0);
 
        lp->tx_started = 0;
        lp->tx_queue = 0;
@@ -564,6 +696,7 @@ net_rx(struct device *dev)
 /* The inverse routine to net_open(). */
 static int net_close(struct device *dev)
 {
+/*     struct net_local *lp = (struct net_local *)dev->priv;*/
        int ioaddr = dev->base_addr;
 
        dev->tbusy = 1;
@@ -572,7 +705,15 @@ static int net_close(struct device *dev)
        /* Set configuration register 0 to disable Tx and Rx. */
        outb(0xda, ioaddr + CONFIG_0);
 
-       /* Update the statistics -- ToDo. */
+       /* No statistic counters on the chip to update. */
+
+#if 0
+       /* Disable the IRQ on boards where it is feasible. */
+       if (lp->jumpered) {
+               outb(0x00, ioaddr + IOCONFIG1);
+               free_irq(dev->irq, dev);
+       }
+#endif
 
        /* Power-down the chip.  Green, green, green! */
        outb(0x00, ioaddr + CONFIG_1);
@@ -582,44 +723,90 @@ static int net_close(struct device *dev)
        return 0;
 }
 
-/* Get the current statistics. This may be called with the card open or
-   closed. */
-   
-static struct net_device_stats *net_get_stats(struct device *dev)
+/* Get the current statistics.
+   This may be called with the card open or closed.
+   There are no on-chip counters, so this function is trivial.
+*/
+static struct enet_statistics *
+net_get_stats(struct device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
+       return &lp->stats;
+}
 
-       cli();
-       /* ToDo: Update the statistics from the device registers. */
-       sti();
+/*
+  Set the multicast/promiscuous mode for this adaptor.
+*/
 
-       return &lp->stats;
+/* The little-endian AUTODIN II ethernet CRC calculation.
+   N.B. Do not use for bulk data, use a table-based routine instead.
+   This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline unsigned ether_crc_le(int length, unsigned char *data)
+{
+       unsigned int crc = 0xffffffff;  /* Initial value. */
+       while(--length >= 0) {
+               unsigned char current_octet = *data++;
+               int bit;
+               for (bit = 8; --bit >= 0; current_octet >>= 1) {
+                       if ((crc ^ current_octet) & 1) {
+                               crc >>= 1;
+                               crc ^= ethernet_polynomial_le;
+                       } else
+                               crc >>= 1;
+               }
+       }
+       return crc;
 }
 
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1     Promiscuous mode, receive all packets
-   num_addrs == 0      Normal mode, clear multicast list
-   num_addrs > 0       Multicast mode, receive normal and MC packets, and do
-                       best-effort filtering.
- */
 static void
-set_multicast_list(struct device *dev)
+set_rx_mode(struct device *dev)
 {
-       short ioaddr = dev->base_addr;
-       if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
-       {
-               /*
-                *      We must make the kernel realise we had to move
-                *      into promisc mode or we start all out war on
-                *      the cable. - AC
-                */
-               dev->flags|=IFF_PROMISC;
+       int ioaddr = dev->base_addr;
+       struct net_local *lp = (struct net_local *)dev->priv;
+       unsigned char mc_filter[8];              /* Multicast hash filter */
+       long flags;
+       int i;
 
+       if (dev->flags & IFF_PROMISC) {
+               /* Unconditionally log net taps. */
+               printk("%s: Promiscuous mode enabled.\n", dev->name);
+               memset(mc_filter, 0xff, sizeof(mc_filter));
                outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
+       } else if (dev->mc_count > MC_FILTERBREAK
+                          ||  (dev->flags & IFF_ALLMULTI)) {
+               /* Too many to filter perfectly -- accept all multicasts. */
+               memset(mc_filter, 0xff, sizeof(mc_filter));
+               outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
+       } else if (dev->mc_count == 0) {
+               memset(mc_filter, 0x00, sizeof(mc_filter));
+               outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
+       } else {
+               struct dev_mc_list *mclist;
+               int i;
+
+               memset(mc_filter, 0, sizeof(mc_filter));
+               for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+                        i++, mclist = mclist->next)
+                       set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26,
+                                       mc_filter);
        }
-       else
-               outb(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
+
+       save_flags(flags);
+       cli();
+       if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
+               int saved_bank = inw(ioaddr + CONFIG_0);
+               /* Switch to bank 1 and set the multicast table. */
+               outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
+               for (i = 0; i < 8; i++)
+                       outb(mc_filter[i], ioaddr + 8 + i);
+               memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
+               outw(saved_bank, ioaddr + CONFIG_0);
+       }
+       restore_flags(flags);
+       return;
 }
+
 #ifdef MODULE
 static char devicename[9] = { 0, };
 static struct device dev_at1700 = {
@@ -630,8 +817,6 @@ static struct device dev_at1700 = {
 
 static int io = 0x260;
 static int irq = 0;
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
 
 int init_module(void)
 {
@@ -649,22 +834,28 @@ int init_module(void)
 void
 cleanup_module(void)
 {
+       struct net_local *lp = dev_at1700.priv;
        unregister_netdev(&dev_at1700);
+       if(lp->mca_slot)
+       {
+               mca_mark_as_unused(lp->mca_slot);
+       }
        kfree(dev_at1700.priv);
        dev_at1700.priv = NULL;
 
        /* If we don't do this, we can't re-insmod it later. */
-       free_irq(dev_at1700.irq, &dev_at1700);
+       free_irq(dev_at1700.irq, NULL);
        release_region(dev_at1700.base_addr, AT1700_IO_EXTENT);
 }
 #endif /* MODULE */
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c at1700.c"
- *  version-control: t
- *  kept-new-versions: 5
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c"
+ *  alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c"
  *  tab-width: 4
+ *  c-basic-offset: 4
  *  c-indent-level: 4
  * End:
  */
+
index 527cd044336ee9a46440c246d88598820ef03ea4..f781abbf356b727bb703a924f6ad17cc64048d29 100644 (file)
  *     Changes by Christopher Turcksin <wabbit@rtfc.demon.co.uk>
  *     + Now compiles ok as a module again.
  *
- *     Changes by Paul Norton (p.norton@computer.org) :
+ *     Changes by Paul Norton (pnorton@ieee.org) :
  *      + moved the header manipulation code in tr_tx and tr_rx to
  *        net/802/tr.c. (July 12 1997)
  *      + add retry and timeout on open if cable disconnected. (May 5 1998)
  *      + lifted 2000 byte mtu limit. now depends on shared-RAM size.
  *        May 25 1998)
+ *      + can't allocate 2k recv buff at 8k shared-RAM. (20 October 1998)
  */
 
 #ifdef PCMCIA
@@ -93,8 +94,8 @@
 
 /* version and credits */
 static char *version =
-"ibmtr.c: v1.3.57  8/ 7/94 Peter De Schrijver and Mark Swanson\n"
-"         v2.1.106 6/22/98 Paul Norton <p.norton@computer.org>\n";
+"ibmtr.c: v1.3.57   8/ 7/94 Peter De Schrijver and Mark Swanson\n"
+"         v2.1.125 10/20/98 Paul Norton <pnorton@ieee.org>\n";
 
 static char pcchannelid[] = {
        0x05, 0x00, 0x04, 0x09,
@@ -416,7 +417,7 @@ __initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr))
 
                        timeout = jiffies + TR_SPIN_INTERVAL;
                        while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN))
-                               if (jiffies > timeout) {
+                               if (time_after(jiffies, timeout)) {
                                        DPRINTK("Hardware timeout during initialization.\n");
                                        kfree_s(ti, sizeof(struct tok_info));
                                        return -ENODEV;
@@ -634,56 +635,56 @@ __initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr))
        switch (ti->mapped_ram_size) {
        case  16 : /* 8KB shared RAM */
                ti->dhb_size4mb  = MIN(ti->dhb_size4mb, 2048);
-               ti->rbuf_len4 = 2048;
-               ti->rbuf_cnt4 = 1;
+               ti->rbuf_len4 = 1032;
+               ti->rbuf_cnt4 = 2;
                ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048);
-               ti->rbuf_len16 = 2048;
-               ti->rbuf_cnt16 = 1;
+               ti->rbuf_len16 = 1032;
+               ti->rbuf_cnt16 = 2;
                break;
        case  32 : /* 16KB shared RAM */
                ti->dhb_size4mb  = MIN(ti->dhb_size4mb, 4464);
-               ti->rbuf_len4 = 512;
+               ti->rbuf_len4 = 520;
                ti->rbuf_cnt4 = 9;
                ti->dhb_size16mb = MIN(ti->dhb_size16mb, 4096);
-               ti->rbuf_len16 = 2048;
-               ti->rbuf_cnt16 = 2;
+               ti->rbuf_len16 = 1032; /* 1024 usable */
+               ti->rbuf_cnt16 = 4;
                break;
        case  64 : /* 32KB shared RAM */
                ti->dhb_size4mb  = MIN(ti->dhb_size4mb, 4464);
-               ti->rbuf_len4 = 2048;
-               ti->rbuf_cnt4 = 3;
+               ti->rbuf_len4 = 1032;
+               ti->rbuf_cnt4 = 6;
                ti->dhb_size16mb = MIN(ti->dhb_size16mb, 10240);
-               ti->rbuf_len16 = 2048;
-               ti->rbuf_cnt16 = 5;
+               ti->rbuf_len16 = 1032;
+               ti->rbuf_cnt16 = 10;
                break;
        case 127 : /* 63KB shared RAM */
                ti->dhb_size4mb  = MIN(ti->dhb_size4mb, 4464);
-               ti->rbuf_len4 = 2048;
-               ti->rbuf_cnt4 = 3;
+               ti->rbuf_len4 = 1032;
+               ti->rbuf_cnt4 = 6;
                ti->dhb_size16mb = MIN(ti->dhb_size16mb, 16384);
-               ti->rbuf_len16 = 2048;
-               ti->rbuf_cnt16 = 8;
+               ti->rbuf_len16 = 1032;
+               ti->rbuf_cnt16 = 16;
                break;
        case 128 : /* 64KB shared RAM */
                ti->dhb_size4mb  = MIN(ti->dhb_size4mb, 4464);
-               ti->rbuf_len4 = 2048;
-               ti->rbuf_cnt4 = 3;
+               ti->rbuf_len4 = 1032;
+               ti->rbuf_cnt4 = 6;
                ti->dhb_size16mb = MIN(ti->dhb_size16mb, 17960);
-               ti->rbuf_len16 = 2048;
-               ti->rbuf_cnt16 = 9;
+               ti->rbuf_len16 = 1032;
+               ti->rbuf_cnt16 = 18;
                break;
        default  :
                ti->dhb_size4mb  = 2048;
-               ti->rbuf_len4 = 2048;
-               ti->rbuf_cnt4 = 1;
+               ti->rbuf_len4 = 1032;
+               ti->rbuf_cnt4 = 2;
                ti->dhb_size16mb = 2048;
-               ti->rbuf_len16 = 2048;
-               ti->rbuf_cnt16 = 1;
+               ti->rbuf_len16 = 1032;
+               ti->rbuf_cnt16 = 2;
                break;
        }
 
-       ti->maxmtu16 = ti->dhb_size16mb-((ti->rbuf_cnt16)<<3)-TR_HLEN;
-       ti->maxmtu4  = ti->dhb_size4mb-((ti->rbuf_cnt4)<<3)-TR_HLEN;
+       ti->maxmtu16 = (ti->rbuf_len16*ti->rbuf_cnt16)-((ti->rbuf_cnt16)<<3)-TR_HLEN;
+       ti->maxmtu4  = (ti->rbuf_len4*ti->rbuf_cnt4)-((ti->rbuf_cnt4)<<3)-TR_HLEN;
        DPRINTK("Maximum MTU 16Mbps: %d, 4Mbps: %d\n",
                ti->maxmtu16, ti->maxmtu4);
 
index df22a0ee7fcfc937cd0e04878f0f7090d92d501a..ac0d6b27e6701d5230e3deaafa7a491a1c608b3d 100644 (file)
@@ -62,12 +62,6 @@ static const char *version =
 
 static struct ipddp_route *ipddp_route_list = NULL;
 
-/*
- *      The name of the card. Is used for messages and in the requests for
- *      io regions, irqs and dma channels
- */
-static const char *cardname = "ipddp";
-
 #ifdef CONFIG_IPDDP_ENCAP
 static int ipddp_mode = IPDDP_ENCAP;
 #else
index 69ed516f0cd182758279ef758889f66339d7a1ae..1c2534328cc2d5f836f561c763ed88cf1efc1684 100644 (file)
@@ -1,6 +1,6 @@
 /* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
 /*
-       Written 1997 by Donald Becker.
+       Written 1997-1998 by Donald Becker.
 
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
 
        Support and updates available at
        http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html
+
+       Twister-tuning code contributed by Kinston <shangh@realtek.com.tw>.
 */
 
 static const char *version =
-"rtl8139.c:v0.14 12/9/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
+"rtl8139.c:v1.04 9/22/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
 
 /* A few user-configurable values. */
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
+static int max_interrupt_work = 20;
+#define rtl8129_debug debug
+static int rtl8129_debug = 1;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
+static int multicast_filter_limit = 32;
+
+/* Used to pass the full-duplex flag, etc. */
+#define MAX_UNITS 8            /* More are supported, limit only on options */
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 /* Size of the in-memory receive ring. */
 #define RX_BUF_LEN_IDX 3                       /* 0==8K, 1==16K, 2==32K, 3==64K */
@@ -37,11 +50,11 @@ static int max_interrupt_work = 10;
 /* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024. */
 #define RX_FIFO_THRESH 4               /* Rx buffer level before first PCI xfer.  */
 #define RX_DMA_BURST   4               /* Maximum PCI burst, '4' is 256 bytes */
-#define TX_DMA_BURST   4
+#define TX_DMA_BURST   4               /* Calculate as 16<<val. */
 
 /* Operational parameters that usually are not changed. */
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((4000*HZ)/1000)
+#define TX_TIMEOUT  (4*HZ)
 
 #include <linux/config.h>
 #ifdef MODULE
@@ -59,79 +72,49 @@ static int max_interrupt_work = 10;
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <asm/processor.h>             /* Processor type for cache alignment. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
 
-/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
    This is only in the support-all-kernels source code. */
-#include <linux/version.h>             /* Evil, but neccessary */
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x)                  /* What to put in timer->expires.  */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#define virt_to_bus(addr)  ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-
-#else  /* 1.3.0 and later */
 #define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-#endif
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
-#ifdef MODULE
-#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
-char kernel_version[] = UTS_RELEASE;
-#endif
-#else
-#undef MOD_INC_USE_COUNT
-#define MOD_INC_USE_COUNT
-#undef MOD_DEC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-#endif /* 1.3.38 */
-
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
 #include <linux/delay.h>
-#endif
 
-#ifdef SA_SHIRQ
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+#if LINUX_VERSION_CODE < 0x20123
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#endif
+#if LINUX_VERSION_CODE <= 0x20139
+#define        net_device_stats enet_statistics
 #else
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+#define NETSTATS_VER2
 #endif
-
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
+#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
+/* Grrrr, the PCI code changed, but did not consider CardBus... */
 #include <linux/bios32.h>
+#define PCI_SUPPORT_VER1
+#else
+#define PCI_SUPPORT_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20159
+#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
+#else
+#define dev_free_skb(skb) dev_kfree_skb(skb);
 #endif
 
 /* The I/O extent. */
 #define RTL8129_TOTAL_SIZE 0x80
 
-#ifdef HAVE_DEVLIST
-struct netdev_entry rtl8139_drv =
-{"RTL8139", rtl8139_probe, RTL8129_TOTAL_SIZE, NULL};
-#endif
-
-static int rtl8129_debug = 1;
-
 /*
                                Theory of Operation
 
@@ -177,16 +160,45 @@ http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
 IVc. Errata
 
 */
+\f
+
+/* This table drives the PCI probe routines.  It's mostly boilerplate in all
+   of the drivers, and will likely be provided by some future kernel.
+   Note the matching code -- the first table entry matchs all 56** cards but
+   second only the 1234 card.
+*/
+enum pci_flags_bit {
+       PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+       PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+       const char *name;
+       u16     vendor_id, device_id, device_id_mask, flags;
+       int io_size;
+       struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+                                                        long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+
+static struct device * rtl8129_probe1(int pci_bus, int pci_devfn,
+                                                                         struct device *dev, long ioaddr,
+                                                                         int irq, int chp_idx, int fnd_cnt);
+
+static struct pci_id_info pci_tbl[] =
+{{ "RealTek RTL8129 Fast Ethernet",
+   0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ { "RealTek RTL8139 Fast Ethernet",
+   0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ { "RealTek RTL8139 Fast Ethernet (mislabeled)",
+   0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ {0,},                                         /* 0 terminated list. */
+};
+
+/* The capability table matches the chip table above. */
+enum {HAS_MII_XCVR=0x01, HAS_CHIP_XCVR=0x02, HAS_LNK_CHNG=0x04};
+static int rtl_cap_tbl[] = {
+       HAS_MII_XCVR, HAS_CHIP_XCVR|HAS_LNK_CHNG, HAS_CHIP_XCVR|HAS_LNK_CHNG,
+};
 
-#ifndef PCI_VENDOR_ID_REALTEK
-#define PCI_VENDOR_ID_REALTEK          0x10ec
-#endif
-#ifndef PCI_DEVICE_ID_REALTEK_8129
-#define PCI_DEVICE_ID_REALTEK_8129     0x8129
-#endif
-#ifndef PCI_DEVICE_ID_REALTEK_8139
-#define PCI_DEVICE_ID_REALTEK_8139     0x8139
-#endif
 
 /* The rest of these values should never change. */
 #define NUM_TX_DESC    4                       /* Number of Tx descriptor registers. */
@@ -195,7 +207,7 @@ IVc. Errata
 enum RTL8129_registers {
        MAC0=0,                                         /* Ethernet hardware address. */
        MAR0=8,                                         /* Multicast filter. */
-       TxStat0=0x10,                           /* Transmit status (Four 32bit registers). */
+       TxStatus0=0x10,                         /* Transmit status (Four 32bit registers). */
        TxAddr0=0x20,                           /* Tx descriptors (also four 32bit). */
        RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
        ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
@@ -206,7 +218,12 @@ enum RTL8129_registers {
        Cfg9346=0x50, Config0=0x51, Config1=0x52,
        FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B,
        MultiIntr=0x5C, TxSummary=0x60,
-       BMCR=0x62, BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, NWayExpansion=0x6A,
+       MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68,
+       NWayExpansion=0x6A,
+       /* Undocumented registers, but required for proper operation. */
+       FIFOTMS=0x70,   /* FIFO Test Mode Select */
+       CSCR=0x74,      /* Chip Status and Configuration Register. */
+       PARA78=0x78, PARA7c=0x7c,       /* Magic transceiver parameter register. */
 };
 
 enum ChipCmdBits {
@@ -228,25 +245,44 @@ enum RxStatusBits {
        RxBadAlign=0x0002, RxStatusOK=0x0001,
 };
 
+enum CSCRBits {
+       CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
+       CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
+       CSCR_LinkDownCmd=0x0f3c0,
+};     
+
+/* Twister tuning parameters from RealTek.  Completely undocumented. */
+unsigned long param[4][4]={
+       {0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43},
+       {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
+       {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
+       {0x0bb39de43,0x0bb39ce43,0x0bb39ce83,0x0bb39ce83}
+};
+
 struct rtl8129_private {
        char devname[8];                        /* Used only for kernel debugging. */
        const char *product_name;
        struct device *next_module;
        int chip_id;
        int chip_revision;
+       unsigned char pci_bus, pci_devfn;
+#if LINUX_VERSION_CODE > 0x20139
+       struct net_device_stats stats;
+#else
        struct enet_statistics stats;
+#endif
        struct timer_list timer;        /* Media selection timer. */
-       unsigned int cur_rx, cur_tx;            /* The next free and used entries */
-       unsigned int dirty_rx, dirty_tx;
+       unsigned int cur_rx;            /* Index into the Rx buffer of next Rx pkt. */
+       unsigned int cur_tx, dirty_tx, tx_flag;
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        struct sk_buff* tx_skbuff[NUM_TX_DESC];
        unsigned char *tx_buf[NUM_TX_DESC];     /* Tx bounce buffers */
        unsigned char *rx_ring;
        unsigned char *tx_bufs;                         /* Tx bounce buffer region. */
-       unsigned char mc_filter[8];                     /* Current multicast filter. */
        char phys[4];                                           /* MII device addresses. */
        unsigned int tx_full:1;                         /* The Tx queue is full. */
        unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
+       unsigned int duplex_lock:1;                     /* Full-duplex operation requested. */
        unsigned int default_port:4;            /* Last dev->if_port value. */
        unsigned int media2:4;                          /* Secondary monitored media port. */
        unsigned int medialock:1;                       /* Don't sense media type. */
@@ -254,24 +290,21 @@ struct rtl8129_private {
 };
 
 #ifdef MODULE
-/* Used to pass the full-duplex flag, etc. */
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#if LINUX_VERSION_CODE > 0x20118
+#if LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(multicast_filter_limit, "i");
 MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(debug, "i");
 #endif
 #endif
 
-static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
-                                                                        int chip_id, int options, int card_idx);
 static int rtl8129_open(struct device *dev);
-static int read_eeprom(int ioaddr, int location);
-static int mdio_read(int ioaddr, int phy_id, int location);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(struct device *dev, int phy_id, int location);
+static void mdio_write(struct device *dev, int phy_id, int location, int val);
 static void rtl8129_timer(unsigned long data);
 static void rtl8129_tx_timeout(struct device *dev);
 static void rtl8129_init_ring(struct device *dev);
@@ -279,161 +312,138 @@ static int rtl8129_start_xmit(struct sk_buff *skb, struct device *dev);
 static int rtl8129_rx(struct device *dev);
 static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int rtl8129_close(struct device *dev);
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 static struct enet_statistics *rtl8129_get_stats(struct device *dev);
-#ifdef NEW_MULTICAST
+static inline u32 ether_crc(int length, unsigned char *data);
 static void set_rx_mode(struct device *dev);
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
-
 \f
 
-#ifdef MODULE
 /* A list of all installed RTL8129 devices, for removing the driver module. */
 static struct device *root_rtl8129_dev = NULL;
-#endif
+
+/* Ideally we would detect all network cards in slot order.  That would
+   be best done a central PCI probe dispatch, which wouldn't work
+   well when dynamically adding drivers.  So instead we detect just the
+   Rtl81*9 cards in slot order. */
 
 int rtl8139_probe(struct device *dev)
 {
        int cards_found = 0;
-       static int pci_index = 0;       /* Static, for multiple probe calls. */
+       int pci_index = 0;
+       unsigned char pci_bus, pci_device_fn;
 
-       /* Ideally we would detect all network cards in slot order.  That would
-          be best done a central PCI probe dispatch, which wouldn't work
-          well with the current structure.  So instead we detect just the
-          Rtl81*9 cards in slot order. */
+       if ( ! pcibios_present())
+               return -ENODEV;
 
-       if (pci_present()) {
-               unsigned char pci_bus, pci_device_fn;
+       for (;pci_index < 0xff; pci_index++) {
+               u16 vendor, device, pci_command, new_command;
+               int chip_idx, irq;
+               long ioaddr;
 
-               for (;pci_index < 0xff; pci_index++) {
-                       unsigned char pci_latency;
-#if LINUX_VERSION_CODE >= 0x20155
-                       unsigned int pci_irq_line;
-                       struct pci_dev *pdev;
-#else
-                       unsigned char pci_irq_line;
-#endif
-                       unsigned short pci_command, new_command, vendor, device;
-                       unsigned int pci_ioaddr;
-
-                       if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-#ifdef REVERSE_PROBE_ORDER
-                                                                       0xff - pci_index,
-#else
-                                                                       pci_index,
-#endif
-                                                                       &pci_bus, &pci_device_fn)
-                               != PCIBIOS_SUCCESSFUL)
+               if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
+                                                               &pci_bus, &pci_device_fn)
+                       != PCIBIOS_SUCCESSFUL)
+                       break;
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_VENDOR_ID, &vendor);
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_DEVICE_ID, &device);
+
+               for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+                       if (vendor == pci_tbl[chip_idx].vendor_id
+                               && (device & pci_tbl[chip_idx].device_id_mask) ==
+                               pci_tbl[chip_idx].device_id)
                                break;
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_VENDOR_ID, &vendor);
-                       if (vendor != PCI_VENDOR_ID_REALTEK)
-                               continue;
-
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_DEVICE_ID, &device);
-#if LINUX_VERSION_CODE >= 0x20155
-                       pdev = pci_find_slot(pci_bus, pci_device_fn);
-                       pci_irq_line = pdev->irq;
-                       pci_ioaddr = pdev->base_address[0];
+               if (pci_tbl[chip_idx].vendor_id == 0)           /* Compiled out! */
+                       continue;
+
+               {
+#if defined(PCI_SUPPORT_VER2)
+                       struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       ioaddr = pdev->base_address[0] & ~3;
+                       irq = pdev->irq;
 #else
+                       u32 pci_ioaddr;
+                       u8 pci_irq_line;
                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                                                                         PCI_INTERRUPT_LINE, &pci_irq_line);
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                                                          PCI_BASE_ADDRESS_0, &pci_ioaddr);
+                       ioaddr = pci_ioaddr & ~3;
+                       irq = pci_irq_line;
 #endif
-                       /* Remove I/O space marker in bit 0. */
-                       pci_ioaddr &= ~3;
-
-                       if (device != PCI_DEVICE_ID_REALTEK_8129
-                               &&  device != PCI_DEVICE_ID_REALTEK_8139) {
-                               printk(KERN_NOTICE"Unknown RealTek PCI ethernet chip type "
-                                          "%4.4x detected: not configured.\n", device);
-                               continue;
-                       }
-                       if (check_region(pci_ioaddr, RTL8129_TOTAL_SIZE))
-                               continue;
-
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_COMMAND, &pci_command);
-                       new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
-                       if (pci_command != new_command) {
-                               printk(KERN_INFO "  The PCI BIOS has not enabled this"
-                                          " device!  Updating PCI config %4.4x->%4.4x.\n",
-                                          pci_command, new_command);
-                               pcibios_write_config_word(pci_bus, pci_device_fn,
-                                                                                 PCI_COMMAND, new_command);
-                       }
+               }
 
-#ifdef MODULE
-                       dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device,
-                                                                options[cards_found], cards_found);
-#else
-                       dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device,
-                                                                dev ? dev->mem_start : 0, -1);
-#endif
+               if ((pci_tbl[chip_idx].flags & PCI_USES_IO) &&
+                       check_region(ioaddr, pci_tbl[chip_idx].io_size))
+                       continue;
+
+               /* Activate the card: fix for brain-damaged Win98 BIOSes. */
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_COMMAND, &pci_command);
+               new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
+               if (pci_command != new_command) {
+                       printk(KERN_INFO "  The PCI BIOS has not enabled the"
+                                  " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
+                                  pci_bus, pci_device_fn, pci_command, new_command);
+                       pcibios_write_config_word(pci_bus, pci_device_fn,
+                                                                         PCI_COMMAND, new_command);
+               }
+
+               dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
+                                                                          irq, chip_idx, cards_found);
 
-                       if (dev) {
-                               pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                                PCI_LATENCY_TIMER, &pci_latency);
-                               if (pci_latency < 32) {
-                                       printk(KERN_NOTICE"  PCI latency timer (CFLT) is "
-                                                  "unreasonably low at %d.  Setting to 64 clocks.\n",
-                                                  pci_latency);
-                                       pcibios_write_config_byte(pci_bus, pci_device_fn,
-                                                                                         PCI_LATENCY_TIMER, 64);
-                               } else if (rtl8129_debug > 1)
-                                       printk(KERN_INFO"  PCI latency timer (CFLT) is %#x.\n",
-                                                  pci_latency);
-                               dev = 0;
-                               cards_found++;
+               if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
+                       u8 pci_latency;
+                       pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                        PCI_LATENCY_TIMER, &pci_latency);
+                       if (pci_latency < 32) {
+                               printk(KERN_NOTICE "  PCI latency timer (CFLT) is "
+                                          "unreasonably low at %d.  Setting to 64 clocks.\n",
+                                          pci_latency);
+                               pcibios_write_config_byte(pci_bus, pci_device_fn,
+                                                                                 PCI_LATENCY_TIMER, 64);
                        }
                }
+               dev = 0;
+               cards_found++;
        }
 
-#if defined (MODULE)
-       return cards_found;
-#else
        return cards_found ? 0 : -ENODEV;
-#endif
 }
 
-static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
-                                                                  int chip_id, int options, int card_idx)
+static struct device * rtl8129_probe1(int pci_bus, int pci_devfn,
+                                                                         struct device *dev, long ioaddr,
+                                                                         int irq, int chip_idx, int found_cnt)
 {
        static int did_version = 0;                     /* Already printed version info. */
        struct rtl8129_private *tp;
-       int i;
+       int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0;
 
        if (rtl8129_debug > 0  &&  did_version++ == 0)
                printk(KERN_INFO "%s", version);
 
        dev = init_etherdev(dev, 0);
 
-       printk(KERN_INFO "%s: RealTek RTL%x at %#3x, IRQ %d, ",
-                  dev->name, chip_id, ioaddr, irq);
+       printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
+                  dev->name, pci_tbl[chip_idx].name, ioaddr, irq);
 
        /* Bring the chip out of low-power mode. */
        outb(0x00, ioaddr + Config1);
 
-       /* Perhaps this should be read from the EEPROM? */
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + MAC0 + i);
+       if (read_eeprom(ioaddr, 0) != 0xffff)
+               for (i = 0; i < 3; i++)
+                       ((u16 *)(dev->dev_addr))[i] = read_eeprom(ioaddr, i + 7);
+       else
+               for (i = 0; i < 6; i++)
+                       dev->dev_addr[i] = inb(ioaddr + MAC0 + i);
 
        for (i = 0; i < 5; i++)
                printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x.\n", dev->dev_addr[i]);
 
-       if (rtl8129_debug > 1) {
-               printk(KERN_INFO "%s: EEPROM contents\n", dev->name);
-               for (i = 0; i < 64; i++)
-                       printk(" %4.4x%s", read_eeprom(ioaddr, i),
-                                  i%16 == 15 ? "\n"KERN_INFO : "");
-       }
-
        /* We do a request_region() to register /proc/ioports info. */
-       request_region(ioaddr, RTL8129_TOTAL_SIZE, "RealTek RTL8129/39 Fast Ethernet");
+       request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
 
        dev->base_addr = ioaddr;
        dev->irq = irq;
@@ -443,22 +453,21 @@ static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
        memset(tp, 0, sizeof(*tp));
        dev->priv = tp;
 
-#ifdef MODULE
        tp->next_module = root_rtl8129_dev;
        root_rtl8129_dev = dev;
-#endif
 
-       tp->chip_id = chip_id;
+       tp->chip_id = chip_idx;
+       tp->pci_bus = pci_bus;
+       tp->pci_devfn = pci_devfn;
 
        /* Find the connected MII xcvrs.
           Doing this in open() would allow detecting external xcvrs later, but
           takes too much time. */
-       if (chip_id == 0x8129) {
+       if (rtl_cap_tbl[chip_idx] & HAS_MII_XCVR) {
                int phy, phy_idx;
                for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
                         phy++) {
-                       int mii_status = mdio_read(ioaddr, phy, 1);
-
+                       int mii_status = mdio_read(dev, phy, 1);
                        if (mii_status != 0xffff  && mii_status != 0x0000) {
                                tp->phys[phy_idx++] = phy;
                                printk(KERN_INFO "%s: MII transceiver found at address %d.\n",
@@ -472,7 +481,7 @@ static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
                        tp->phys[0] = -1;
                }
        } else {
-                       tp->phys[0] = -1;
+                       tp->phys[0] = 32;
        }
 
        /* Put the chip into low-power mode. */
@@ -481,18 +490,21 @@ static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
        outb('H', ioaddr + HltClk);             /* 'R' would leave the clock running. */
 
        /* The lower four bits are the media type. */
-       if (options > 0) {
-               tp->full_duplex = (options & 16) ? 1 : 0;
-               tp->default_port = options & 15;
+       if (option > 0) {
+               tp->full_duplex = (option & 0x200) ? 1 : 0;
+               tp->default_port = option & 15;
                if (tp->default_port)
                        tp->medialock = 1;
        }
-#ifdef MODULE
-       if (card_idx >= 0) {
-               if (full_duplex[card_idx] >= 0)
-                       tp->full_duplex = full_duplex[card_idx];
+
+       if (found_cnt < MAX_UNITS  &&  full_duplex[found_cnt] > 0)
+               tp->full_duplex = full_duplex[found_cnt];
+
+       if (tp->full_duplex) {
+               printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
+               mdio_write(dev, tp->phys[0], 4, 0x141);
+               tp->duplex_lock = 1;
        }
-#endif
 
        /* The Rtl8129-specific entries in the device structure. */
        dev->open = &rtl8129_open;
@@ -500,6 +512,7 @@ static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
        dev->stop = &rtl8129_close;
        dev->get_stats = &rtl8129_get_stats;
        dev->set_multicast_list = &set_rx_mode;
+       dev->do_ioctl = &mii_ioctl;
 
        return dev;
 }
@@ -516,24 +529,21 @@ static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
 #define EE_ENB                 (0x80 | EE_CS)
 
 /* Delay between EEPROM clock transitions.
-   The 1.2 code is a "nasty" timing loop, but PC compatible machines are
-   *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro.  */
-#ifdef _LINUX_DELAY_H
-#define eeprom_delay(nanosec)  udelay((nanosec + 999)/1000)
-#else
-#define eeprom_delay(nanosec)  do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
+   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
+ */
+
+#define eeprom_delay() inl(ee_addr)
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD   (5 << 6)
 #define EE_READ_CMD            (6 << 6)
 #define EE_ERASE_CMD   (7 << 6)
 
-static int read_eeprom(int ioaddr, int location)
+static int read_eeprom(long ioaddr, int location)
 {
        int i;
-       unsigned short retval = 0;
-       short ee_addr = ioaddr + Cfg9346;
+       unsigned retval = 0;
+       long ee_addr = ioaddr + Cfg9346;
        int read_cmd = location | EE_READ_CMD;
 
        outb(EE_ENB & ~EE_CS, ee_addr);
@@ -541,22 +551,21 @@ static int read_eeprom(int ioaddr, int location)
 
        /* Shift the read command bits out. */
        for (i = 10; i >= 0; i--) {
-               short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
                outb(EE_ENB | dataval, ee_addr);
-               eeprom_delay(100);
+               eeprom_delay();
                outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay(150);
-               outb(EE_ENB | dataval, ee_addr);        /* Finish EEPROM a clock tick. */
-               eeprom_delay(250);
+               eeprom_delay();
        }
        outb(EE_ENB, ee_addr);
+       eeprom_delay();
 
        for (i = 16; i > 0; i--) {
                outb(EE_ENB | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay(100);
+               eeprom_delay();
                retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0);
                outb(EE_ENB, ee_addr);
-               eeprom_delay(100);
+               eeprom_delay();
        }
 
        /* Terminate the EEPROM access. */
@@ -566,43 +575,50 @@ static int read_eeprom(int ioaddr, int location)
 
 /* MII serial management: mostly bogus for now. */
 /* Read and write the MII management registers using software-generated
-   serial MDIO protocol.  The maxium data clock rate is 2.5 Mhz. */
+   serial MDIO protocol.
+   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues. */
 #define MDIO_DIR               0x80
 #define MDIO_DATA_OUT  0x04
 #define MDIO_DATA_IN   0x02
 #define MDIO_CLK               0x01
-#ifdef _LINUX_DELAY_H
-#define mdio_delay()   udelay(1) /* Really 400ns. */
-#else
-#define mdio_delay()   __SLOW_DOWN_IO;
-#endif
+#define MDIO_WRITE0 (MDIO_DIR)
+#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
+
+#define mdio_delay()   inb(mdio_addr)
+
+static char mii_2_8139_map[8] = {MII_BMCR, MII_BMSR, 0, 0, NWayAdvert,
+                                                                NWayLPAR, NWayExpansion, 0 };
 
 /* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync(int ioaddr)
+static void mdio_sync(long mdio_addr)
 {
        int i;
-       int mdio_addr = ioaddr + MII_SMI;
 
        for (i = 32; i >= 0; i--) {
-               outb(MDIO_DIR | MDIO_DATA_OUT, mdio_addr);
+               outb(MDIO_WRITE1, mdio_addr);
                mdio_delay();
-               outb(MDIO_DIR | MDIO_DATA_OUT | MDIO_CLK, mdio_addr);
+               outb(MDIO_WRITE1 | MDIO_CLK, mdio_addr);
                mdio_delay();
        }
        return;
 }
-static int mdio_read(int ioaddr, int phy_id, int location)
+static int mdio_read(struct device *dev, int phy_id, int location)
 {
-       int i;
-       int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+       long mdio_addr = dev->base_addr + MII_SMI;
+       int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
        int retval = 0;
-       int mdio_addr = ioaddr + MII_SMI;
+       int i;
 
-       mdio_sync(ioaddr);
+       if ((phy_id & 0x1f) == 0) {     /* Really a 8139.  Use internal registers. */
+               return location < 8 && mii_2_8139_map[location] ?
+                       inw(dev->base_addr + mii_2_8139_map[location]) : 0;
+       }
+       mdio_sync(mdio_addr);
        /* Shift the read command bits out. */
        for (i = 15; i >= 0; i--) {
-               int dataval =
-                 (read_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
+               int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
 
                outb(MDIO_DIR | dataval, mdio_addr);
                mdio_delay();
@@ -620,31 +636,52 @@ static int mdio_read(int ioaddr, int phy_id, int location)
        }
        return (retval>>1) & 0xffff;
 }
+
+static void mdio_write(struct device *dev, int phy_id, int location, int value)
+{
+       long mdio_addr = dev->base_addr + MII_SMI;
+       int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+       int i;
+
+       if (phy_id == 32) {                     /* Really a 8139.  Use internal registers. */
+               if (location < 8  &&  mii_2_8139_map[location])
+                       outw(value, dev->base_addr + mii_2_8139_map[location]);
+               return;
+       }
+       mdio_sync(mdio_addr);
+
+       /* Shift the command bits out. */
+       for (i = 31; i >= 0; i--) {
+               int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+               outb(dataval, mdio_addr);
+               mdio_delay();
+               outb(dataval | MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+       /* Clear out extra bits. */
+       for (i = 2; i > 0; i--) {
+               outb(0, mdio_addr);
+               mdio_delay();
+               outb(MDIO_CLK, mdio_addr);
+               mdio_delay();
+       }
+       return;
+}
+
 \f
 static int
 rtl8129_open(struct device *dev)
 {
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        int i;
-       int full_duplex = 0;
 
        /* Soft reset the chip. */
        outb(CmdReset, ioaddr + ChipCmd);
 
-#ifdef SA_SHIRQ
-       if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ,
-                                       "RealTek RTL8129/39 Fast Ethernet", dev)) {
+       if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev)) {
                return -EAGAIN;
        }
-#else
-       if (irq2dev_map[dev->irq] != NULL
-               || (irq2dev_map[dev->irq] = dev) == NULL
-               || dev->irq == 0
-               || request_irq(dev->irq, &rtl8129_interrupt, 0, "RTL8129")) {
-               return -EAGAIN;
-       }
-#endif
 
        MOD_INC_USE_COUNT;
 
@@ -660,20 +697,10 @@ rtl8129_open(struct device *dev)
        }
        rtl8129_init_ring(dev);
 
-#ifndef final_version
-       /* Used to monitor rx ring overflow. */
-       memset(tp->rx_ring + RX_BUF_LEN, 0xcc, 16);
-#endif
-
        /* Check that the chip has finished the reset. */
        for (i = 1000; i > 0; i--)
                if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
                        break;
-#ifndef final_version
-       if (rtl8129_debug > 2)
-               printk(KERN_DEBUG"%s: reset finished with status %2.2x after %d loops.\n",
-                          dev->name, inb(ioaddr + ChipCmd), 1000-i);
-#endif
 
        for (i = 0; i < 6; i++)
                outb(dev->dev_addr[i], ioaddr + MAC0 + i);
@@ -683,29 +710,26 @@ rtl8129_open(struct device *dev)
        outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
                 ioaddr + RxConfig);
        outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig);
+       tp->tx_flag = (TX_FIFO_THRESH<<11) & 0x003f0000;
 
-       full_duplex = tp->full_duplex;
-       if (tp->phys[0] >= 0  ||  tp->chip_id == 0x8139) {
-               u16 mii_reg5;
-               if (tp->chip_id == 0x8139)
-                       mii_reg5 = inw(ioaddr + NWayLPAR);
-               else
-                       mii_reg5 = mdio_read(ioaddr, tp->phys[0], 5);
+       tp->full_duplex = tp->duplex_lock;
+       if (tp->phys[0] >= 0  ||  (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)) {
+               u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
                if (mii_reg5 == 0xffff)
                        ;                                       /* Not there */
                else if ((mii_reg5 & 0x0100) == 0x0100
                                 || (mii_reg5 & 0x00C0) == 0x0040)
-                       full_duplex = 1;
+                       tp->full_duplex = 1;
                if (rtl8129_debug > 1)
                        printk(KERN_INFO"%s: Setting %s%s-duplex based on"
                                   " auto-negotiated partner ability %4.4x.\n", dev->name,
                                   mii_reg5 == 0 ? "" :
                                   (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
-                                  full_duplex ? "full" : "half", mii_reg5);
+                                  tp->full_duplex ? "full" : "half", mii_reg5);
        }
 
        outb(0xC0, ioaddr + Cfg9346);
-       outb(full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
        outb(0x00, ioaddr + Cfg9346);
 
        outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf);
@@ -715,13 +739,6 @@ rtl8129_open(struct device *dev)
        set_rx_mode(dev);
 
        outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
-#ifndef final_version
-       if (rtl8129_debug > 1)
-               printk(KERN_DEBUG"%s:  In rtl8129_open() Tx/Rx Config %8.8x/%8.8x"
-                          " Chip Config %2.2x/%2.2x.\n",
-                          dev->name, inl(ioaddr + TxConfig), inl(ioaddr + RxConfig),
-                          inb(ioaddr + Config0), inb(ioaddr + Config1));
-#endif
 
        dev->tbusy = 0;
        dev->interrupt = 0;
@@ -732,10 +749,10 @@ rtl8129_open(struct device *dev)
                | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
 
        if (rtl8129_debug > 1)
-               printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %4.4x IRQ %d"
+               printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d"
                           " GP Pins %2.2x %s-duplex.\n",
                           dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData),
-                          full_duplex ? "full" : "half");
+                          tp->full_duplex ? "full" : "half");
 
        /* Set the timer to switch to check for link beat and perhaps switch
           to an alternate media type. */
@@ -752,26 +769,26 @@ static void rtl8129_timer(unsigned long data)
 {
        struct device *dev = (struct device *)data;
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        int next_tick = 0;
-
-       if (tp->chip_id == 0x8139) {
-               u16 mii_reg5 = inw(ioaddr + NWayLPAR);
-               if ((mii_reg5 & 0x0100) == 0x0100
-                       || (mii_reg5 & 0x00C0) == 0x0040)
-                       if ( ! tp->full_duplex) {
-                               tp->full_duplex = 1;
-                               if (rtl8129_debug > 0)
-                                       printk(KERN_INFO "%s: Switching to full-duplex based on "
-                                                  "link partner ability of %4.4x.\n",
-                                                  dev->name, mii_reg5);
-                               outb(0xC0, ioaddr + Cfg9346);
-                               outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
-                               outb(0x00, ioaddr + Cfg9346);
-                       }
+       int mii_reg5 = mdio_read(dev, tp->phys[0], 5);
+
+       if (! tp->duplex_lock  &&  mii_reg5 != 0xffff) {
+               int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+               if (tp->full_duplex != duplex) {
+                       tp->full_duplex = duplex;
+                       printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
+                                  " partner ability of %4.4x.\n", dev->name,
+                                  tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5);
+                       outb(0xC0, ioaddr + Cfg9346);
+                       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+                       outb(0x00, ioaddr + Cfg9346);
+               }
+               next_tick = 60*HZ;
        }
+
        if (rtl8129_debug > 2) {
-               if (tp->chip_id == 0x8129)
+               if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)
                        printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n",
                                   dev->name, inb(ioaddr + GPPinData));
                else
@@ -794,33 +811,80 @@ static void rtl8129_timer(unsigned long data)
 static void rtl8129_tx_timeout(struct device *dev)
 {
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int ioaddr = dev->base_addr;
-       int i;
+       long ioaddr = dev->base_addr;
+       int mii_reg, i;
 
        if (rtl8129_debug > 0)
-               printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x.\n",
-                          dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus));
+               printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x "
+                          "media %2.2x.\n",
+                          dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus),
+                          inb(ioaddr + GPPinData));
+
+       /* Disable interrupts by clearing the interrupt mask. */
+       outw(0x0000, ioaddr + IntrMask);
+       /* Emit info to figure out what went wrong. */
+       printk("%s: Tx queue start entry %d  dirty entry %d.\n",
+                  dev->name, tp->cur_tx, tp->dirty_tx);
        for (i = 0; i < NUM_TX_DESC; i++)
                printk(KERN_DEBUG"%s:  Tx descriptor %d is %8.8x.%s\n",
-                          dev->name, i, inl(ioaddr + TxStat0 + i*4),
+                          dev->name, i, inl(ioaddr + TxStatus0 + i*4),
                           i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
-       if (tp->chip_id == 0x8129) {
-               int mii_reg;
-               printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]);
-               for (mii_reg = 0; mii_reg < 8; mii_reg++)
-                       printk(" %4.4x", mdio_read(ioaddr, tp->phys[0], mii_reg));
-               printk(".\n");
-       } else {
-               printk(KERN_DEBUG"%s: MII status register is %4.4x.\n",
-                          dev->name, inw(ioaddr + BMSR));
-       }
-       /* Restart the chip Tx process. */
+       printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]);
+       for (mii_reg = 0; mii_reg < 8; mii_reg++)
+               printk(" %4.4x", mdio_read(dev, tp->phys[0], mii_reg));
+       printk(".\n");
+
+       /* Soft reset the chip. */
+       outb(CmdReset, ioaddr + ChipCmd);
+       /* Check that the chip has finished the reset. */
+       for (i = 1000; i > 0; i--)
+               if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
+                       break;
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + MAC0 + i);
+
+       outb(0x00, ioaddr + Cfg9346);
+       tp->cur_rx = 0;
+       /* Must enable Tx/Rx before setting transfer thresholds! */
        outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
-       /* Continue from any transmit abort. */
-       outl((TX_DMA_BURST<<8) || 0x03000001, ioaddr + TxConfig);
+       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
+                ioaddr + RxConfig);
+       outl((TX_DMA_BURST<<8), ioaddr + TxConfig);
+       set_rx_mode(dev);
+       {                                                       /* Save the unsent Tx packets. */
+               struct sk_buff *saved_skb[NUM_TX_DESC], *skb;
+               int j;
+               for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++)
+                       saved_skb[j] = tp->tx_skbuff[tp->dirty_tx % NUM_TX_DESC];
+               tp->dirty_tx = tp->cur_tx = 0;
+
+               for (i = 0; i < j; i++) {
+                       skb = tp->tx_skbuff[i] = saved_skb[i];
+                       if ((long)skb->data & 3) {              /* Must use alignment buffer. */
+                               memcpy(tp->tx_buf[i], skb->data, skb->len);
+                               outl(virt_to_bus(tp->tx_buf[i]), ioaddr + TxAddr0 + i*4);
+                       } else
+                               outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + i*4);
+                       /* Note: the chip doesn't have auto-pad! */
+                       outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
+                                ioaddr + TxStatus0 + i*4);
+               }
+               tp->cur_tx = i;
+               while (i < NUM_TX_DESC)
+                       tp->tx_skbuff[i] = 0;
+               if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
+                       dev->tbusy = 0;
+                       tp->tx_full = 0;
+               } else {
+                       tp->tx_full = 1;
+               }
+       }
 
        dev->trans_start = jiffies;
        tp->stats.tx_errors++;
+       /* Enable all known interrupts by setting the interrupt mask. */
+       outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
+                | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
        return;
 }
 
@@ -833,8 +897,8 @@ rtl8129_init_ring(struct device *dev)
        int i;
 
        tp->tx_full = 0;
-       tp->cur_rx = tp->cur_tx = 0;
-       tp->dirty_rx = tp->dirty_tx = 0;
+       tp->cur_rx = 0;
+       tp->dirty_tx = tp->cur_tx = 0;
 
        for (i = 0; i < NUM_TX_DESC; i++) {
                tp->tx_skbuff[i] = 0;
@@ -846,20 +910,9 @@ static int
 rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
 {
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        int entry;
 
-#ifndef final_version
-       if (skb == NULL || skb->len <= 0) {
-               printk(KERN_ERR"%s: Obsolete driver Tx request made: skbuff==NULL.\n",
-                          dev->name);
-#if 0
-               dev_tint(dev);
-#endif
-               return 0;
-       }
-#endif
-
        /* Block a timer-based transmit from overlapping.  This could better be
           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
@@ -879,12 +932,11 @@ rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
        } else
                outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + entry*4);
        /* Note: the chip doesn't have auto-pad! */
-       outl(((TX_FIFO_THRESH<<11) & 0x003f0000) |
-                (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
-                ioaddr + TxStat0 + entry*4);
+       outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
+                ioaddr + TxStatus0 + entry*4);
 
        if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
-               dev->tbusy = 0;
+               clear_bit(0, (void*)&dev->tbusy);
        } else {
                tp->tx_full = 1;
        }
@@ -892,36 +944,36 @@ rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
        dev->trans_start = jiffies;
        if (rtl8129_debug > 4)
                printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n",
-                          dev->name, skb->data, skb->len, entry);
+                          dev->name, skb->data, (int)skb->len, entry);
 
        return 0;
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-#ifdef SA_SHIRQ
        struct device *dev = (struct device *)dev_instance;
-#else
-       struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
-       struct rtl8129_private *tp;
-       int ioaddr, boguscnt = max_interrupt_work;
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       int boguscnt = max_interrupt_work;
        int status;
+       long ioaddr = dev->base_addr;
 
-       if (dev == NULL) {
-               printk (KERN_ERR"rtl8139_interrupt(): IRQ %d for unknown device.\n",
-                               irq);
+#if defined(__i386__)
+       /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+               printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+                          dev->name);
+               dev->interrupt = 0;     /* Avoid halting machine. */
                return;
        }
-
-       ioaddr = dev->base_addr;
-       tp = (struct rtl8129_private *)dev->priv;
-       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+#else
+       if (dev->interrupt) {
                printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
                return;
        }
+       dev->interrupt = 1;
+#endif
 
        do {
                status = inw(ioaddr + IntrStatus);
@@ -944,9 +996,9 @@ static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *r
 
                        for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) {
                                int entry = dirty_tx % NUM_TX_DESC;
-                               int txstatus = inl(ioaddr + TxStat0 + entry*4);
+                               int txstatus = inl(ioaddr + TxStatus0 + entry*4);
 
-                               if ( ! (txstatus & TxHostOwns))
+                               if ( ! (txstatus & (TxStatOK | TxUnderrun | TxAborted)))
                                        break;                  /* It still hasn't been Txed */
 
                                /* Note: TxCarrierLost is always asserted at 100mbps. */
@@ -973,15 +1025,20 @@ static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *r
                                        /* No count for tp->stats.tx_deferred */
 #endif
                                        if (txstatus & TxUnderrun) {
-                                               /* Todo: increase the Tx FIFO threshold. */
+                                               /* Add 64 to the Tx FIFO threshold. */
+                                               if (tp->tx_flag <  0x00300000)
+                                                       tp->tx_flag += 0x00020000;
                                                tp->stats.tx_fifo_errors++;
                                        }
                                        tp->stats.collisions += (txstatus >> 24) & 15;
+#if LINUX_VERSION_CODE > 0x20119
+                                       tp->stats.tx_bytes += txstatus & 0x7ff;
+#endif
                                        tp->stats.tx_packets++;
                                }
 
                                /* Free the original skb. */
-                               dev_kfree_skb(tp->tx_skbuff[entry]);
+                               dev_free_skb(tp->tx_skbuff[entry]);
                                tp->tx_skbuff[entry] = 0;
                        }
 
@@ -993,8 +1050,7 @@ static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *r
                        }
 #endif
 
-                       if (tp->tx_full && dev->tbusy
-                               && dirty_tx > tp->cur_tx - NUM_TX_DESC) {
+                       if (tp->tx_full  &&  dirty_tx > tp->cur_tx - NUM_TX_DESC) {
                                /* The ring is no longer full, clear tbusy. */
                                tp->tx_full = 0;
                                dev->tbusy = 0;
@@ -1007,17 +1063,29 @@ static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *r
                /* Check uncommon events with one test. */
                if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver
                                          |TxErr|RxErr)) {
+                       if (rtl8129_debug > 2)
+                               printk(KERN_NOTICE"%s: Abnormal interrupt, status %8.8x.\n",
+                                          dev->name, status);
 
-#ifndef final_version
-                       if (rtl8129_debug > 0)
-                               printk(KERN_DEBUG"%s: Unusual error, status %4.4x.\n",
-                                                          dev->name, status);
-#endif
-
+                       if (status == 0xffffffff)
+                               break;
                        /* Update the error count. */
                        tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
                        outl(0, ioaddr + RxMissed);
 
+                       if ((status & RxUnderrun)  &&
+                               (rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) {
+                               /* Really link-change on new chips. */
+                               int lpar = inw(ioaddr + NWayLPAR);
+                               int duplex = (lpar&0x0100)||(lpar & 0x01C0) == 0x0040; 
+                               if (tp->full_duplex != duplex) {
+                                       tp->full_duplex = duplex;
+                                       outb(0xC0, ioaddr + Cfg9346);
+                                       outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+                                       outb(0x00, ioaddr + Cfg9346);
+                               }
+                               status &= ~RxUnderrun;
+                       }
                        if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
                                tp->stats.rx_errors++;
 
@@ -1028,7 +1096,14 @@ static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *r
                                tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN;
                                outw(tp->cur_rx - 16, ioaddr + RxBufPtr);
                        }
-                       /* Error sources cleared above. */
+                       if (status & PCIErr) {
+                               u32 pci_cmd_status;
+                               pcibios_read_config_dword(tp->pci_bus, tp->pci_devfn,
+                                                                                 PCI_COMMAND, &pci_cmd_status);
+
+                               printk(KERN_ERR "%s: PCI Bus error %4.4x.\n",
+                                          dev->name, pci_cmd_status);
+                       }
                }
                if (--boguscnt < 0) {
                        printk(KERN_WARNING"%s: Too much work at interrupt, "
@@ -1044,29 +1119,20 @@ static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *r
                printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n",
                           dev->name, inl(ioaddr + IntrStatus));
 
-#ifndef final_version
-       /* Code that should never be run!  Perhaps remove after testing.. */
-       {
-               static int stopit = 10;
-               if (dev->start == 0  &&  --stopit < 0) {
-                       printk(KERN_ERR"%s: Emergency stop, looping startup interrupt.\n",
-                                  dev->name);
-                       FREE_IRQ(irq, dev);
-               }
-       }
-#endif
-
+#if defined(__i386__)
+       clear_bit(0, (void*)&dev->interrupt);
+#else
        dev->interrupt = 0;
+#endif
        return;
 }
 
-/* Todo: The data sheet doesn't describe the Rx ring at all, so I'm winging
-   it here until I have a chip to play with. 8/30/97 */
-static int
-rtl8129_rx(struct device *dev)
+/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
+   field alignments and semantics. */
+static int rtl8129_rx(struct device *dev)
 {
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        unsigned char *rx_ring = tp->rx_ring;
        u16 cur_rx = tp->cur_rx;
 
@@ -1077,9 +1143,9 @@ rtl8129_rx(struct device *dev)
                           inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
 
        while ((inb(ioaddr + ChipCmd) & 1) == 0) {
-               u16 ring_offset = cur_rx % RX_BUF_LEN;
+               int ring_offset = cur_rx % RX_BUF_LEN;
                u32 rx_status = *(u32*)(rx_ring + ring_offset);
-               u16 rx_size = rx_status >> 16;
+               int rx_size = rx_status >> 16;
 
                if (rtl8129_debug > 4) {
                        int i;
@@ -1105,12 +1171,18 @@ rtl8129_rx(struct device *dev)
                                tp->stats.rx_frame_errors++;
                        if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++;
                        if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++;
+                       /* Reset the receiver, based on RealTek recommendation. (Bug?) */
+                       tp->cur_rx = 0;
+                       outb(CmdTxEnb, ioaddr + ChipCmd);
+                       outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+                       outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) |
+                                (RX_DMA_BURST<<8), ioaddr + RxConfig);
                } else {
                        /* Malloc up new buffer, compatible with net-2e. */
                        /* Omit the four octet CRC from the length. */
                        struct sk_buff *skb;
 
-                       skb = DEV_ALLOC_SKB(rx_size + 2);
+                       skb = dev_alloc_skb(rx_size + 2);
                        if (skb == NULL) {
                                printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n",
                                           dev->name);
@@ -1129,26 +1201,32 @@ rtl8129_rx(struct device *dev)
                                           rx_size-semi_count);
                                if (rtl8129_debug > 4) {
                                        int i;
-                                       printk(KERN_DEBUG"%s:  Frame wrap @%d", dev->name, semi_count);
+                                       printk(KERN_DEBUG"%s:  Frame wrap @%d",
+                                                  dev->name, semi_count);
                                        for (i = 0; i < 16; i++)
                                                printk(" %2.2x", rx_ring[i]);
                                        printk(".\n");
                                        memset(rx_ring, 0xcc, 16);
                                }
-                       } else
+                       } else {
+#if 1  /* USE_IP_COPYSUM */
+                               eth_copy_and_sum(skb, &rx_ring[ring_offset + 4],
+                                                                rx_size, 0);
+                               skb_put(skb, rx_size);
+#else
                                memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4],
                                           rx_size);
-#if LINUX_VERSION_CODE >= 0x10300
-                       skb->protocol = eth_type_trans(skb, dev);
-#else
-                       skb->len = rx_size;
 #endif
+                       }
+                       skb->protocol = eth_type_trans(skb, dev);
                        netif_rx(skb);
+#if LINUX_VERSION_CODE > 0x20119
+                       tp->stats.rx_bytes += rx_size;
+#endif
                        tp->stats.rx_packets++;
                }
 
-               cur_rx += rx_size + 4;
-               cur_rx = (cur_rx + 3) & ~3;
+               cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
                outw(cur_rx - 16, ioaddr + RxBufPtr);
        }
        if (rtl8129_debug > 4)
@@ -1163,7 +1241,7 @@ rtl8129_rx(struct device *dev)
 static int
 rtl8129_close(struct device *dev)
 {
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
        int i;
 
@@ -1186,29 +1264,11 @@ rtl8129_close(struct device *dev)
 
        del_timer(&tp->timer);
 
-#ifdef SA_SHIRQ
        free_irq(dev->irq, dev);
-#else
-       free_irq(dev->irq);
-       irq2dev_map[dev->irq] = 0;
-#endif
-
-#ifndef final_version
-       /* Used to monitor rx ring overflow. */
-       for (i = 0; i < 16; i++)
-               if (tp->rx_ring[RX_BUF_LEN+i] != 0xcc) {
-                       printk(KERN_WARNING"%s: Rx ring overflowed!  Values are ",
-                                  dev->name);
-                       for (i = 0; i < 16; i++)
-                               printk(" %2.2x", tp->rx_ring[RX_BUF_LEN + i]);
-                       printk(".\n");
-                       break;
-               }
-#endif
 
        for (i = 0; i < NUM_TX_DESC; i++) {
                if (tp->tx_skbuff[i])
-                       dev_kfree_skb(tp->tx_skbuff[i]);
+                       dev_free_skb(tp->tx_skbuff[i]);
                tp->tx_skbuff[i] = 0;
        }
        kfree(tp->rx_ring);
@@ -1224,11 +1284,33 @@ rtl8129_close(struct device *dev)
        return 0;
 }
 
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+       u16 *data = (u16 *)&rq->ifr_data;
+
+       switch(cmd) {
+       case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
+               data[0] = tp->phys[0] & 0x3f;
+               /* Fall Through */
+       case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
+               data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+               return 0;
+       case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
+               if (!suser())
+                       return -EPERM;
+               mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
 static struct enet_statistics *
 rtl8129_get_stats(struct device *dev)
 {
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
 
        if (dev->start) {
                tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
@@ -1239,94 +1321,69 @@ rtl8129_get_stats(struct device *dev)
 }
 
 /* Set or clear the multicast filter for this adaptor.
-   Note that we only use exclusion around actually queueing the
-   new frame, not around filling tp->setup_frame.  This is non-deterministic
-   when re-entered but still correct. */
-
-/* The little-endian AUTODIN II ethernet CRC calculation.
-   N.B. Do not use for bulk data, use a table-based routine instead.
-   This is common code and should be moved to net/core/crc.c */
-static unsigned const ethernet_polynomial_le = 0xedb88320U;
-static inline unsigned ether_crc_le(int length, unsigned char *data)
+   This routine is not state sensitive and need not be SMP locked. */
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
 {
-       unsigned int crc = 0xffffffff;  /* Initial value. */
-       while(--length >= 0) {
+    int crc = -1;
+
+    while(--length >= 0) {
                unsigned char current_octet = *data++;
                int bit;
-               for (bit = 8; --bit >= 0; current_octet >>= 1) {
-                       if ((crc ^ current_octet) & 1) {
-                               crc >>= 1;
-                               crc ^= ethernet_polynomial_le;
-                       } else
-                               crc >>= 1;
-               }
-       }
-       return crc;
+               for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+                       crc = (crc << 1) ^
+                               ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+    }
+    return crc;
 }
 
+/* Bits in RxConfig. */
+enum rx_mode_bits {
+       AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08,
+       AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
+};
 
-static void
-#ifdef NEW_MULTICAST
-set_rx_mode(struct device *dev)
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_rx_mode(struct device *dev)
 {
-       int ioaddr = dev->base_addr;
-       struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
-       unsigned char mc_filter[8];              /* Multicast hash filter */
-       int i;
+       long ioaddr = dev->base_addr;
+       u32 mc_filter[2];                /* Multicast hash filter */
+       int i, rx_mode;
+
+       if (rtl8129_debug > 3)
+               printk(KERN_DEBUG"%s:   set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
+                          dev->name, dev->flags, inl(ioaddr + RxConfig));
 
-       if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous. */
+       /* Note: do not reorder, GCC is clever about common statements. */
+       if (dev->flags & IFF_PROMISC) {
                /* Unconditionally log net taps. */
                printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name);
-               memset(mc_filter, 0xff, sizeof(mc_filter));
-               outb(0x0F, ioaddr + RxConfig);
-       } else if ((dev->mc_count > 1000)  ||  (dev->flags & IFF_ALLMULTI)) {
+               rx_mode = AcceptBroadcast|AcceptMulticast|AcceptMyPhys|AcceptAllPhys;
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+       } else if ((dev->mc_count > multicast_filter_limit)
+                          ||  (dev->flags & IFF_ALLMULTI)) {
                /* Too many to filter perfectly -- accept all multicasts. */
-               memset(mc_filter, 0xff, sizeof(mc_filter));
-               outb(0x0E, ioaddr + RxConfig);
-       } else if (dev->mc_count == 0) {
-               outb(0x0A, ioaddr + RxConfig);
-               return;
+               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
        } else {
                struct dev_mc_list *mclist;
-
-               memset(mc_filter, 0, sizeof(mc_filter));
+               rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+               mc_filter[1] = mc_filter[0] = 0;
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                         i++, mclist = mclist->next)
-                       set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
-                                       mc_filter);
-       }
-       /* ToDo: perhaps we need to stop the Tx and Rx process here? */
-       if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
-               for (i = 0; i < 2; i++)
-                       outl(((u32 *)mc_filter)[i], ioaddr + MAR0 + i*4);
-               memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+                       set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter);
        }
-       if (rtl8129_debug > 3)
-               printk(KERN_DEBUG"%s:   set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
-                          dev->name, dev->flags, inl(ioaddr + RxConfig));
+       /* We can safely update without stopping the chip. */
+       outb(rx_mode, ioaddr + RxConfig);
+       outl(mc_filter[0], ioaddr + MAR0 + 0);
+       outl(mc_filter[1], ioaddr + MAR0 + 4);
        return;
 }
 \f
 #ifdef MODULE
-
-/* An additional parameter that may be passed in... */
-static int debug = -1;
-
-int
-init_module(void)
+int init_module(void)
 {
-       int cards_found;
-
-       if (debug >= 0)
-               rtl8129_debug = debug;
-
-       root_rtl8129_dev = NULL;
-       cards_found = rtl8139_probe(0);
-
-       return cards_found ? 0 : -ENODEV;
+       return rtl8139_probe(0);
 }
 
 void
@@ -1336,9 +1393,13 @@ cleanup_module(void)
 
        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
        while (root_rtl8129_dev) {
-               next_dev = ((struct rtl8129_private *)root_rtl8129_dev->priv)->next_module;
+               struct rtl8129_private *tp =
+                       (struct rtl8129_private *)root_rtl8129_dev->priv;
+               next_dev = tp->next_module;
                unregister_netdev(root_rtl8129_dev);
-               release_region(root_rtl8129_dev->base_addr, RTL8129_TOTAL_SIZE);
+               release_region(root_rtl8129_dev->base_addr,
+                                          pci_tbl[tp->chip_id].io_size);
+               kfree(tp);
                kfree(root_rtl8129_dev);
                root_rtl8129_dev = next_dev;
        }
@@ -1348,7 +1409,8 @@ cleanup_module(void)
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
index e886eecce134da28e9ebd92b803c35c7b18705ef..af0282e627d1184728b1f02686c30c260f03abf0 100644 (file)
@@ -1270,6 +1270,8 @@ static int get_status_info(char *buffer, char **start, off_t req_offset, int req
 }
 
 static const char proc_strip_status_name[] = "strip";
+
+#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_strip_get_status_info =
 {
     PROC_NET_STRIP_STATUS,             /* unsigned short low_ino */
@@ -1284,7 +1286,7 @@ static struct proc_dir_entry proc_strip_get_status_info =
     NULL, NULL, NULL,                  /* struct proc_dir_entry *next, *parent, *subdir; */
     NULL                               /* void *data; */
 };
-
+#endif /* CONFIG_PROC_FS */
 
 /************************************************************************/
 /* Sending routines                                                    */
@@ -2847,10 +2849,12 @@ int strip_init_ctrl_dev(struct device *dummy)
     /*
      * Register the status file with /proc
      */
+#ifdef CONFIG_PROC_FS 
     if (proc_net_register(&proc_strip_get_status_info) != 0)
     {
         printk(KERN_ERR "strip: status proc_net_register() failed.\n");
     }
+#endif
 
 #ifdef MODULE
      return status;
@@ -2881,7 +2885,9 @@ void cleanup_module(void)
         strip_free(struct_strip_list);
 
     /* Unregister with the /proc/net file here. */
+#ifdef CONFIG_PROC_FS
     proc_net_unregister(PROC_NET_STRIP_STATUS);
+#endif
 
     if ((i = tty_register_ldisc(N_STRIP, NULL)))
         printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
index 93f5f7ea7e703be50306aaf7f9cf6c4e1fb38cdd..fec55899f635b17b151962804a0e15f9392cd65b 100644 (file)
@@ -1,11 +1,12 @@
 /* yellowfin.c: A Packet Engines G-NIC ethernet driver for linux. */
 /*
-       Written 1997 by Donald Becker.
+       Written 1997-1998 by Donald Becker.
 
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
 
        This driver is for the Packet Engines G-NIC PCI Gigabit Ethernet adapter.
+       It also supports the Symbios Logic version of the same chip core.
 
        The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
        Center of Excellence in Space Data and Information Sciences
@@ -15,7 +16,9 @@
        http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html
 */
 
-static const char *version = "yellowfin.c:v0.10 12/5/97 becker@cesdis.gsfc.nasa.gov\n";
+static const char *version =
+"yellowfin.c:v1.02 7/26/98  Written by Donald Becker, becker@cesdis.edu\n"
+" http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html\n";
 
 /* A few user-configurable values. */
 
@@ -27,7 +30,7 @@ static int mtu = 0;
 static int bogus_rx = 0;
 static int dma_ctrl = 0x004A0263;                      /* Constrained by errata */
 static int fifo_cfg = 0x0020;                          /* Bypass external Tx FIFO. */
-#elif YF_NEW
+#elif YF_NEW                                   /* A future perfect board :->.  */
 static int dma_ctrl = 0x00CAC277;                      /* Override when loading module! */
 static int fifo_cfg = 0x0028;
 #else
@@ -36,8 +39,18 @@ static int fifo_cfg = 0x0020;                                /* Bypass external Tx FIFO. */
 #endif
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
-   Setting to > 1518 effectively disables this feature. */
-static const int rx_copybreak = 100;
+   Setting to > 1514 effectively disables this feature. */
+static int rx_copybreak = 0;
+
+/* Used to pass the media type, etc.
+   No media types are currently defined.  These exist for driver
+   interoperability.
+*/
+#define MAX_UNITS 8                            /* More are supported, limit only on options */
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+/* Operational parameters that are set at compile time. */
 
 /* Keep the ring sizes a power of two for efficiency.
    Making the Tx ring too large decreases the effectiveness of channel
@@ -80,68 +93,35 @@ static const int rx_copybreak = 100;
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-/* Kernel compatibility defines, common to David Hind's PCMCIA package.
-   This is only in the support-all-kernels source code. */
+/* Kernel compatibility defines, most common to the PCCard package. */
 #include <linux/version.h>             /* Evil, but neccessary */
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x)                  /* What to put in timer->expires.  */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#define virt_to_bus(addr)  ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-
-#else  /* 1.3.0 and later */
 #define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-#endif
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
-#ifdef MODULE
-#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
+#if (LINUX_VERSION_CODE >= 0x20100)
 char kernel_version[] = UTS_RELEASE;
 #endif
-#else
-#undef MOD_INC_USE_COUNT
-#define MOD_INC_USE_COUNT
-#undef MOD_DEC_USE_COUNT
-#define MOD_DEC_USE_COUNT
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
 #endif
-#endif /* 1.3.38 */
-
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
-#include <linux/delay.h>
+#if LINUX_VERSION_CODE <= 0x20139
+#define        net_device_stats enet_statistics
+#define NETSTATS_VER2
 #endif
-#if (LINUX_VERSION_CODE >= 0x20100)
-#ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
+#if LINUX_VERSION_CODE < 0x20155
+#define PCI_SUPPORT_VER1
+#define pci_present pcibios_present
 #endif
-#endif
-#ifdef SA_SHIRQ
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+#if LINUX_VERSION_CODE < 0x20159
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
 #else
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
 #endif
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#include <linux/bios32.h>
-#endif
-
-static const char *card_name = "Yellowfin G-NIC Gbit Ethernet";
 
 /* The PCI I/O space extent. */
 #define YELLOWFIN_TOTAL_SIZE 0x100
 
-#ifdef HAVE_DEVLIST
-struct netdev_entry yellowfin_drv =
-{card_name, yellowfin_pci_probe, YELLOWFIN_TOTAL_SIZE, NULL};
-#endif
-
-#ifdef YELLOWFIN_DEBUG
-int yellowfin_debug = YELLOWFIN_DEBUG;
-#else
 int yellowfin_debug = 1;
-#endif
 
 /*
                                Theory of Operation
@@ -204,15 +184,20 @@ clears both the tx_full and tbusy flags.
 IV. Notes
 
 Thanks to Kim Stearns of Packet Engines for providing a pair of G-NIC boards.
+Thanks to Bruce Faust of Digitalscape for providing both their SYM53C885 board
+and an AlphaStation to verifty the Alpha port!
 
 IVb. References
 
 Yellowfin Engineering Design Specification, 4/23/97 Preliminary/Confidential
+Symbios SYM53C885 PCI-SCSI/Fast Ethernet Multifunction Controller Preliminary
+   Data Manual v3.0
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
 http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
 
 IVc. Errata
 
-See Packet Engines confidential appendix.
+See Packet Engines confidential appendix (prototype chips only).
 
 */
 \f
@@ -221,6 +206,7 @@ See Packet Engines confidential appendix.
 
 #ifndef PCI_VENDOR_ID_PKT_ENG          /* To be defined in linux/pci.h */
 #define PCI_VENDOR_ID_PKT_ENG                  0x1000 /* Hmm, likely number.. */
+#define PCI_DEVICE_ID_SYM58C885                        0x0701
 #define PCI_DEVICE_ID_YELLOWFIN                        0x0702
 #endif
 
@@ -228,6 +214,21 @@ See Packet Engines confidential appendix.
 
 static void yellowfin_timer(unsigned long data);
 
+enum capability_flags {HasMII=1, FullTxStatus=2};
+struct chip_info {
+       u16     vendor_id, device_id, device_id_mask, pci_flags;
+       const char *name;
+       void (*media_timer)(unsigned long data);
+       u32 chip_rev;                           /* As read from ChipRev, not PCI dev ID. */
+       int flags;
+} chip_tbl[] = {
+       {0x1000, 0x0702, 0xffff, 0, "Yellowfin G-NIC Gbit Ethernet",
+        yellowfin_timer, 0x0702, FullTxStatus},
+       {0x1000, 0x0701, 0xffff, 0, "Symbios SYM83C885",
+        yellowfin_timer, 0x0701, HasMII},
+       {0,},
+};
+
 /* Offsets to the Yellowfin registers.  Various sizes and alignments. */
 enum yellowfin_offsets {
        TxCtrl=0x00, TxStatus=0x04, TxPtr=0x0C,
@@ -235,8 +236,13 @@ enum yellowfin_offsets {
        RxCtrl=0x40, RxStatus=0x44, RxPtr=0x4C,
        RxIntrSel=0x50, RxBranchSel=0x54, RxWaitSel=0x58,
        EventStatus=0x80, IntrEnb=0x82, IntrClear=0x84, IntrStatus=0x86,
-       ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, RxDepth=0xB8, FlowCtrl=0xBC,
+       ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, FrameGap0=0xA2, FrameGap1=0xA4,
+       MII_Cmd=0xA6, MII_Addr=0xA8, MII_Wr_Data=0xAA, MII_Rd_Data=0xAC,
+       MII_Status=0xAE,
+       RxDepth=0xB8, FlowCtrl=0xBC,
        AddrMode=0xD0, StnAddr=0xD2, HashTbl=0xD8, FIFOcfg=0xF8,
+       EEStatus=0xF0, EECtrl=0xF1, EEAddr=0xF2, EERead=0xF3, EEWrite=0xF4,
+       EEFeature=0xF5,
 };
 
 /* The Yellowfin Rx and Tx buffer descriptors. */
@@ -280,27 +286,34 @@ struct yellowfin_private {
        struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
        const char *product_name;
        struct device *next_module;
+       /* The addresses of receive-in-place skbuffs. */
+       struct sk_buff* rx_skbuff[RX_RING_SIZE];
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        struct sk_buff* tx_skbuff[TX_RING_SIZE];
        struct tx_status_words tx_status[TX_RING_SIZE];
-       /* The addresses of receive-in-place skbuffs. */
-       struct sk_buff* rx_skbuff[RX_RING_SIZE];
-       int chip_id;
-       struct enet_statistics stats;
        struct timer_list timer;        /* Media selection timer. */
-       unsigned int cur_rx, cur_tx;            /* The next free ring entry */
-       unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
+       struct enet_statistics stats;
+       /* Frequently used and paired value: keep adjacent for cache effect. */
+       int chip_id;
+       int in_interrupt;
+       struct yellowfin_desc *rx_head_desc;
+       struct tx_status_words *tx_tail_desc;
+       unsigned int cur_rx, dirty_rx;          /* Producer/consumer ring indices */
+       unsigned int cur_tx, dirty_tx;
+       unsigned int rx_buf_sz;                         /* Based on MTU+slack. */
        unsigned int tx_full:1;                         /* The Tx queue is full. */
        unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
+       unsigned int duplex_lock:1;
        unsigned int medialock:1;                       /* Do not sense media. */
        unsigned int default_port:4;            /* Last dev->if_port value. */
+       /* MII transceiver section. */
+       int mii_cnt;                                            /* MII device addresses. */
+       u16 advertising;                                        /* NWay media advertisement */
+       unsigned char phys[2];                          /* MII device addresses. */
        u32 pad[4];                                                     /* Used for 32-byte alignment */
 };
 
 #ifdef MODULE
-/* Used to pass the media type, etc. */
-#define MAX_UNITS 8                            /* More are supported, limit only on options */
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 #if LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
@@ -311,169 +324,163 @@ MODULE_PARM(mtu, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 #endif
 
 #endif
 
-static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq,
-                                                                  int chip_id, int options);
+static struct device *yellowfin_probe1(struct device *dev, long ioaddr,
+                                                                          int irq, int chip_id, int options);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
+#ifdef HAVE_PRIVATE_IOCTL
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+#endif
 static int yellowfin_open(struct device *dev);
 static void yellowfin_timer(unsigned long data);
 static void yellowfin_tx_timeout(struct device *dev);
 static void yellowfin_init_ring(struct device *dev);
 static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev);
+static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int yellowfin_rx(struct device *dev);
-static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs);
+static void yellowfin_error(struct device *dev, int intr_status);
 static int yellowfin_close(struct device *dev);
 static struct enet_statistics *yellowfin_get_stats(struct device *dev);
-#ifdef NEW_MULTICAST
 static void set_rx_mode(struct device *dev);
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
 
 \f
 
-#ifdef MODULE
 /* A list of all installed Yellowfin devices, for removing the driver module. */
 static struct device *root_yellowfin_dev = NULL;
-#endif
 
 int yellowfin_probe(struct device *dev)
 {
        int cards_found = 0;
-       static int pci_index = 0;       /* Static, for multiple probe calls. */
-
-       /* Ideally we would detect all network cards in slot order.  That would
-          be best done a central PCI probe dispatch, which wouldn't work
-          well with the current structure.  So instead we detect just the
-          Yellowfin cards in slot order. */
+       int pci_index = 0;
+       unsigned char pci_bus, pci_device_fn;
+
+       if ( ! pci_present())
+               return -ENODEV;
+
+       for (;pci_index < 0xff; pci_index++) {
+               u8 pci_latency;
+               u16 pci_command, new_command, vendor, device;
+               int chip_idx;
+               int irq;
+               long ioaddr;
+
+               if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+                                                               pci_index,
+                                                               &pci_bus, &pci_device_fn)
+                       != PCIBIOS_SUCCESSFUL)
+                       break;
 
-       if (pci_present()) {
-               unsigned char pci_bus, pci_device_fn;
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_VENDOR_ID, &vendor);
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_DEVICE_ID, &device);
 
-               for (;pci_index < 0xff; pci_index++) {
-#if LINUX_VERSION_CODE >= 0x20155
-                       unsigned int pci_irq_line;
-                       struct pci_dev *pdev;
-#else
-                       unsigned char pci_irq_line;
-#endif
-                       unsigned char pci_latency;
-                       unsigned short pci_command, vendor, device;
-                       unsigned int pci_ioaddr, chip_idx = 0;
-
-#ifdef REVERSE_PROBE_ORDER
-                       if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-                                                                       0xfe - pci_index,
-                                                                       &pci_bus, &pci_device_fn)
-                               != PCIBIOS_SUCCESSFUL)
-                               continue;
-#else
-                       if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-                                                                       pci_index,
-                                                                       &pci_bus, &pci_device_fn)
-                               != PCIBIOS_SUCCESSFUL)
+               for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+                       if (vendor == chip_tbl[chip_idx].vendor_id
+                               && (device & chip_tbl[chip_idx].device_id_mask) ==
+                               chip_tbl[chip_idx].device_id)
                                break;
-#endif
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_VENDOR_ID, &vendor);
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_DEVICE_ID, &device);
-#if LINUX_VERSION_CODE >= 0x20155
-                       pdev = pci_find_slot(pci_bus, pci_device_fn);
-                       pci_irq_line = pdev->irq;
-                       pci_ioaddr = pdev->base_address[0];
+               if (chip_tbl[chip_idx].vendor_id == 0)          /* Compiled out! */
+                       continue;
+
+               {
+#if LINUX_VERSION_CODE >= 0x20155  ||  PCI_SUPPORT_1
+                       struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       ioaddr = pdev->base_address[0];
+                       irq = pdev->irq;
 #else
+                       u32 pci_ioaddr;
+                       u8 pci_irq_line;
                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                                                                         PCI_INTERRUPT_LINE, &pci_irq_line);
                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                                                                          PCI_BASE_ADDRESS_0, &pci_ioaddr);
+                       ioaddr = pci_ioaddr;
+                       irq = pci_irq_line;
 #endif
-                       /* Remove I/O space marker in bit 0. */
-                       pci_ioaddr &= ~3;
-
-                       if (vendor != PCI_VENDOR_ID_PKT_ENG)
-                               continue;
-
-                       if (device != PCI_DEVICE_ID_YELLOWFIN)
-                               continue;
-
-                       if (yellowfin_debug > 2)
-                               printk("Found Packet Engines Yellowfin G-NIC at I/O %#x, IRQ %d.\n",
-                                          pci_ioaddr, pci_irq_line);
+               }
+               /* Remove I/O space marker in bit 0. */
+               ioaddr &= ~3;
+
+               if (yellowfin_debug > 2)
+                       printk(KERN_INFO "Found %s at I/O %#lx, IRQ %d.\n",
+                                  chip_tbl[chip_idx].name, ioaddr, irq);
+
+               if (check_region(ioaddr, YELLOWFIN_TOTAL_SIZE))
+                       continue;
+
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_COMMAND, &pci_command);
+               new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+               if (pci_command != new_command) {
+                       printk(KERN_INFO "  The PCI BIOS has not enabled the"
+                                  " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
+                                  pci_bus, pci_device_fn, pci_command, new_command);
+                       pcibios_write_config_word(pci_bus, pci_device_fn,
+                                                                         PCI_COMMAND, new_command);
+               }
 
-                       if (check_region(pci_ioaddr, YELLOWFIN_TOTAL_SIZE))
-                               continue;
+               dev = yellowfin_probe1(dev, ioaddr, irq, chip_idx, cards_found);
 
-#ifdef MODULE
-                       dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
-                                                cards_found < MAX_UNITS ? options[cards_found] : 0);
-#else
-                       dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
-                                                dev ? dev->mem_start : 0);
-#endif
-
-                       if (dev) {
-                         /* Get and check the bus-master and latency values. */
-                         pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                          PCI_COMMAND, &pci_command);
-                         if ( ! (pci_command & PCI_COMMAND_MASTER)) {
-                               printk("  PCI Master Bit has not been set! Setting...\n");
-                               pci_command |= PCI_COMMAND_MASTER;
-                               pcibios_write_config_word(pci_bus, pci_device_fn,
-                                                                                 PCI_COMMAND, pci_command);
-                         }
-                         pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                          PCI_LATENCY_TIMER, &pci_latency);
-                         if (pci_latency < min_pci_latency) {
-                               printk("  PCI latency timer (CFLT) is unreasonably low at %d."
-                                          "  Setting to %d clocks.\n",
+               if (dev) {
+                       /* Get and check the bus-master and latency values. */
+                       pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                        PCI_LATENCY_TIMER, &pci_latency);
+                       if (pci_latency < min_pci_latency) {
+                               printk(KERN_INFO "  PCI latency timer (CFLT) is "
+                                          "unreasonably low at %d.  Setting to %d clocks.\n",
                                           pci_latency, min_pci_latency);
                                pcibios_write_config_byte(pci_bus, pci_device_fn,
                                                                                  PCI_LATENCY_TIMER, min_pci_latency);
-                         } else if (yellowfin_debug > 1)
-                               printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
-                         dev = 0;
-                         cards_found++;
-                       }
+                       } else if (yellowfin_debug > 1)
+                               printk(KERN_INFO "  PCI latency timer (CFLT) is %#x.\n",
+                                          pci_latency);
+                       dev = 0;
+                       cards_found++;
                }
        }
 
-#if defined (MODULE)
-       return cards_found;
-#else
-       return 0;
-#endif
+       return cards_found ? 0 : -ENODEV;
 }
 
-static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq,
-                                                                  int chip_id, int options)
+static struct device *yellowfin_probe1(struct device *dev, long ioaddr,
+                                                                          int irq, int chip_id, int card_idx)
 {
        static int did_version = 0;                     /* Already printed version info. */
        struct yellowfin_private *yp;
-       int i;
+       int option, i;
 
        if (yellowfin_debug > 0  &&  did_version++ == 0)
                printk(version);
 
        dev = init_etherdev(dev, sizeof(struct yellowfin_private));
 
-       printk("%s: P-E Yellowfin type %8x at %#3x, ",
-                  dev->name, inl(ioaddr + ChipRev), ioaddr);
+       printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
+                  dev->name, chip_tbl[chip_id].name, inl(ioaddr + ChipRev), ioaddr);
 
+       if (inw(ioaddr + ChipRev) == 0x0702)
+               for (i = 0; i < 6; i++)
+                       dev->dev_addr[i] = inb(ioaddr + StnAddr + i);
+       else {
+               int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0);
+               for (i = 0; i < 6; i++)
+                       dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i);
+       }
        for (i = 0; i < 5; i++)
-               printk("%2.2x:", inb(ioaddr + StnAddr + i));
-       printk("%2.2x, IRQ %d.\n", inb(ioaddr + StnAddr + i), irq);
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + StnAddr + i);
+                       printk("%2.2x:", dev->dev_addr[i]);
+       printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
        /* Reset the chip. */
        outl(0x80000000, ioaddr + DMACtrl);
 
-
        /* We do a request_region() only to register /proc/ioports info. */
-       request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, card_name);
+       request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, dev->name);
 
        dev->base_addr = ioaddr;
        dev->irq = irq;
@@ -483,28 +490,28 @@ static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq,
        memset(yp, 0, sizeof(*yp));
        dev->priv = yp;
 
-#ifdef MODULE
        yp->next_module = root_yellowfin_dev;
        root_yellowfin_dev = dev;
-#endif
 
        yp->chip_id = chip_id;
 
-       yp->full_duplex = 1;
-#ifdef YELLOWFIN_DEFAULT_MEDIA
-       yp->default_port = YELLOWFIN_DEFAULT_MEDIA;
-#endif
-#ifdef YELLOWFIN_NO_MEDIA_SWITCH
-       yp->medialock = 1;
-#endif
+       option = card_idx < MAX_UNITS ? options[card_idx] : 0;
+       if (dev->mem_start)
+               option = dev->mem_start;
 
        /* The lower four bits are the media type. */
-       if (options > 0) {
-               yp->full_duplex = (options & 16) ? 1 : 0;
-               yp->default_port = options & 15;
+       if (option > 0) {
+               if (option & 0x200)
+                       yp->full_duplex = 1;
+               yp->default_port = option & 15;
                if (yp->default_port)
                        yp->medialock = 1;
        }
+       if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
+               yp->full_duplex = 1;
+
+       if (yp->full_duplex)
+               yp->duplex_lock = 1;
 
        /* The Yellowfin-specific entries in the device structure. */
        dev->open = &yellowfin_open;
@@ -512,40 +519,88 @@ static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq,
        dev->stop = &yellowfin_close;
        dev->get_stats = &yellowfin_get_stats;
        dev->set_multicast_list = &set_rx_mode;
+#ifdef HAVE_PRIVATE_IOCTL
+       dev->do_ioctl = &mii_ioctl;
+#endif
        if (mtu)
                dev->mtu = mtu;
 
-       /* todo: Reset the xcvr interface and turn on heartbeat. */
+       if (chip_tbl[yp->chip_id].flags & HasMII) {
+               int phy, phy_idx = 0;
+               for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
+                       int mii_status = mdio_read(ioaddr, phy, 1);
+                       if (mii_status != 0xffff  &&
+                               mii_status != 0x0000) {
+                               yp->phys[phy_idx++] = phy;
+                               yp->advertising = mdio_read(ioaddr, phy, 4);
+                               printk(KERN_INFO "%s: MII PHY found at address %d, status "
+                                          "0x%4.4x advertising %4.4x.\n",
+                                          dev->name, phy, mii_status, yp->advertising);
+                       }
+               }
+               yp->mii_cnt = phy_idx;
+       }
 
        return dev;
 }
 
+static int read_eeprom(long ioaddr, int location)
+{
+       int bogus_cnt = 1000;
+
+       outb(location, ioaddr + EEAddr);
+       outb(0x30 | ((location >> 8) & 7), ioaddr + EECtrl);
+       while ((inb(ioaddr + EEStatus) & 0x80)  && --bogus_cnt > 0)
+               ;
+       return inb(ioaddr + EERead);
+}
+
+/* MII Managemen Data I/O accesses.
+   These routines assume the MDIO controller is idle, and do not exit until
+   the command is finished. */
+
+static int mdio_read(long ioaddr, int phy_id, int location)
+{
+       int i;
+
+       outw((phy_id<<8) + location, ioaddr + MII_Addr);
+       outw(1, ioaddr + MII_Cmd);
+       for (i = 10000; i >= 0; i--)
+               if ((inw(ioaddr + MII_Status) & 1) == 0)
+                       break;
+       return inw(ioaddr + MII_Rd_Data);
+}
+
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
+{
+       int i;
+
+       outw((phy_id<<8) + location, ioaddr + MII_Addr);
+       outw(value, ioaddr + MII_Wr_Data);
+
+       /* Wait for the command to finish. */
+       for (i = 10000; i >= 0; i--)
+               if ((inw(ioaddr + MII_Status) & 1) == 0)
+                       break;
+       return;
+}
+
 \f
-static int
-yellowfin_open(struct device *dev)
+static int yellowfin_open(struct device *dev)
 {
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
+       int i;
 
        /* Reset the chip. */
        outl(0x80000000, ioaddr + DMACtrl);
 
-#ifdef SA_SHIRQ
-       if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ,
-                                       card_name, dev)) {
-               return -EAGAIN;
-       }
-#else
-       if (irq2dev_map[dev->irq] != NULL
-               || (irq2dev_map[dev->irq] = dev) == NULL
-               || dev->irq == 0
-               || request_irq(dev->irq, &yellowfin_interrupt, 0, card_name)) {
+       if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, dev->name, dev))
                return -EAGAIN;
-       }
-#endif
 
        if (yellowfin_debug > 1)
-               printk("%s: yellowfin_open() irq %d.\n", dev->name, dev->irq);
+               printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n",
+                          dev->name, dev->irq);
 
        MOD_INC_USE_COUNT;
 
@@ -554,6 +609,9 @@ yellowfin_open(struct device *dev)
        outl(virt_to_bus(yp->rx_ring), ioaddr + RxPtr);
        outl(virt_to_bus(yp->tx_ring), ioaddr + TxPtr);
 
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + StnAddr + i);
+
        /* Set up various condition 'select' registers.
           There are no options here. */
        outl(0x00800080, ioaddr + TxIntrSel);   /* Interrupt on Tx abort */
@@ -575,17 +633,19 @@ yellowfin_open(struct device *dev)
 
        dev->tbusy = 0;
        dev->interrupt = 0;
-
-       /* We are always in full-duplex mode with the current chip! */
-       yp->full_duplex = 1;
+       yp->in_interrupt = 0;
 
        /* Setting the Rx mode will start the Rx process. */
-       outw(0x01CD | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
-#ifdef NEW_MULTICAST
+       if (yp->chip_id == 0) {
+               /* We are always in full-duplex mode with gigabit! */
+               yp->full_duplex = 1;
+               outw(0x01CF, ioaddr + Cnfg);
+       } else {
+               outw(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */
+               outw(0x1018, ioaddr + FrameGap1);
+               outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
+       }
        set_rx_mode(dev);
-#else
-       set_rx_mode(dev, 0, 0);
-#endif
 
        dev->start = 1;
 
@@ -596,7 +656,7 @@ yellowfin_open(struct device *dev)
        outl(0x80008000, ioaddr + TxCtrl);
 
        if (yellowfin_debug > 2) {
-               printk("%s: Done yellowfin_open().\n",
+               printk(KERN_DEBUG "%s: Done yellowfin_open().\n",
                           dev->name);
        }
        /* Set the timer to check for link beat. */
@@ -613,13 +673,36 @@ static void yellowfin_timer(unsigned long data)
 {
        struct device *dev = (struct device *)data;
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        int next_tick = 0;
 
        if (yellowfin_debug > 3) {
-               printk("%s: Yellowfin timer tick, status %8.8x.\n",
-                          dev->name, inl(ioaddr + IntrStatus));
+               printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n",
+                          dev->name, inw(ioaddr + IntrStatus));
+       }
+
+       if (yp->mii_cnt) {
+               int mii_reg1 = mdio_read(ioaddr, yp->phys[0], 1);
+               int mii_reg5 = mdio_read(ioaddr, yp->phys[0], 5);
+               int negotiated = mii_reg5 & yp->advertising;
+               if (yellowfin_debug > 1)
+                       printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "
+                                  "link partner capability %4.4x.\n",
+                                  dev->name, yp->phys[0], mii_reg1, mii_reg5);
+
+               if ( ! yp->duplex_lock &&
+                        ((negotiated & 0x0300) == 0x0100
+                         || (negotiated & 0x00C0) == 0x0040)) {
+                       yp->full_duplex = 1;
+               }
+               outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
+
+               if (mii_reg1 & 0x0004)
+                       next_tick = 60*HZ;
+               else
+                       next_tick = 3*HZ;
        }
+
        if (next_tick) {
                yp->timer.expires = RUN_AT(next_tick);
                add_timer(&yp->timer);
@@ -629,20 +712,22 @@ static void yellowfin_timer(unsigned long data)
 static void yellowfin_tx_timeout(struct device *dev)
 {
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
-       int ioaddr = dev->base_addr;
-       int i;
+       long ioaddr = dev->base_addr;
 
-       printk("%s: Yellowfin transmit timed out, status %8.8x, resetting...\n",
+       printk(KERN_WARNING "%s: Yellowfin transmit timed out, status %8.8x, resetting...\n",
                   dev->name, inl(ioaddr));
 
 #ifndef __alpha__
-  printk("  Rx ring %8.8x: ", (int)yp->rx_ring);
-  for (i = 0; i < RX_RING_SIZE; i++)
-       printk(" %8.8x", (unsigned int)yp->rx_ring[i].status);
-  printk("\n  Tx ring %8.8x: ", (int)yp->tx_ring);
-  for (i = 0; i < TX_RING_SIZE; i++)
-       printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status);
-  printk("\n");
+       {
+               int i;
+               printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)yp->rx_ring);
+               for (i = 0; i < RX_RING_SIZE; i++)
+                       printk(" %8.8x", (unsigned int)yp->rx_ring[i].status);
+               printk("\n"KERN_DEBUG"  Tx ring %8.8x: ", (int)yp->tx_ring);
+               for (i = 0; i < TX_RING_SIZE; i++)
+                       printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status);
+               printk("\n");
+       }
 #endif
 
   /* Perhaps we should reinitialize the hardware here. */
@@ -658,8 +743,7 @@ static void yellowfin_tx_timeout(struct device *dev)
 
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void
-yellowfin_init_ring(struct device *dev)
+static void yellowfin_init_ring(struct device *dev)
 {
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
        int i;
@@ -668,24 +752,23 @@ yellowfin_init_ring(struct device *dev)
        yp->cur_rx = yp->cur_tx = 0;
        yp->dirty_rx = yp->dirty_tx = 0;
 
+       yp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+       yp->rx_head_desc = &yp->rx_ring[0];
+
        for (i = 0; i < RX_RING_SIZE; i++) {
                struct sk_buff *skb;
-               int pkt_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 
-               yp->rx_ring[i].request_cnt = pkt_buf_sz;
+               yp->rx_ring[i].request_cnt = yp->rx_buf_sz;
                yp->rx_ring[i].cmd = CMD_RX_BUF | INTR_ALWAYS;
 
-               skb = DEV_ALLOC_SKB(pkt_buf_sz);
-               skb_reserve(skb, 2);    /* 16 byte align the IP header. */
+               skb = dev_alloc_skb(yp->rx_buf_sz);
                yp->rx_skbuff[i] = skb;
-               if (skb == NULL)
-                       break;                  /* Bad news!  */
-               skb->dev = dev;                 /* Mark as being used by this device. */
-#if LINUX_VERSION_CODE > 0x10300
-               yp->rx_ring[i].addr = virt_to_bus(skb->tail);
-#else
-               yp->rx_ring[i].addr = virt_to_bus(skb->data);
-#endif
+               if (skb) {
+                       skb->dev = dev;                 /* Mark as being used by this device. */
+                       skb_reserve(skb, 2);    /* 16 byte align the IP header. */
+                       yp->rx_ring[i].addr = virt_to_bus(skb->tail);
+               } else if (yp->dirty_rx == 0)
+                       yp->dirty_rx = (unsigned int)(0 - RX_RING_SIZE);
                yp->rx_ring[i].branch_addr = virt_to_bus(&yp->rx_ring[i+1]);
        }
        /* Mark the last entry as wrapping the ring. */
@@ -709,19 +792,26 @@ yellowfin_init_ring(struct device *dev)
                yp->tx_ring[i].cmd = CMD_STOP; /* Branch on Tx error. */
                yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
                i++;
-               yp->tx_ring[i].cmd = CMD_TXSTATUS; /* Interrupt, no wait. */
-               yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]);
-               yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]);
+               if (chip_tbl[yp->chip_id].flags & FullTxStatus) {
+                       yp->tx_ring[i].cmd = CMD_TXSTATUS;
+                       yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]);
+                       yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]);
+               } else {                                /* Symbios chips write only tx_errs word. */
+                       yp->tx_ring[i].cmd = CMD_TXSTATUS | INTR_ALWAYS;
+                       yp->tx_ring[i].request_cnt = 2;
+                       yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2].tx_errs);
+               }
                yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
        }
        /* Wrap ring */
        yp->tx_ring[--i].cmd = CMD_TXSTATUS | BRANCH_ALWAYS | INTR_ALWAYS;
        yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]);
 #endif
+       yp->tx_tail_desc = &yp->tx_status[0];
+       return;
 }
 
-static int
-yellowfin_start_xmit(struct sk_buff *skb, struct device *dev)
+static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev)
 {
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
        unsigned entry;
@@ -773,19 +863,19 @@ yellowfin_start_xmit(struct sk_buff *skb, struct device *dev)
                CMD_TX_PKT | BRANCH_IFTRUE;
 #endif
 
-       /* Todo: explicitly flush cache lines here. */
+       /* Non-x86 Todo: explicitly flush cache lines here. */
 
        /* Wake the potentially-idle transmit channel. */
        outl(0x10001000, dev->base_addr + TxCtrl);
 
        if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1)
-               dev->tbusy = 0;                                 /* Typical path */
+               clear_bit(0, (void*)&dev->tbusy);               /* Typical path */
        else
                yp->tx_full = 1;
        dev->trans_start = jiffies;
 
        if (yellowfin_debug > 4) {
-               printk("%s: Yellowfin transmit frame #%d queued in slot %d.\n",
+               printk(KERN_DEBUG "%s: Yellowfin transmit frame #%d queued in slot %d.\n",
                           dev->name, yp->cur_tx, entry);
        }
        return 0;
@@ -793,302 +883,320 @@ yellowfin_start_xmit(struct sk_buff *skb, struct device *dev)
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-#ifdef SA_SHIRQ                /* Use the now-standard shared IRQ implementation. */
        struct device *dev = (struct device *)dev_instance;
-#else
-       struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
-
-       struct yellowfin_private *lp;
-       int ioaddr, boguscnt = max_interrupt_work;
+       struct yellowfin_private *yp;
+       long ioaddr, boguscnt = max_interrupt_work;
 
+#ifndef final_version                  /* Can never occur. */
        if (dev == NULL) {
-               printk ("yellowfin_interrupt(): irq %d for unknown device.\n", irq);
+               printk (KERN_ERR "yellowfin_interrupt(): irq %d for unknown device.\n", irq);
                return;
        }
+#endif
 
        ioaddr = dev->base_addr;
-       lp = (struct yellowfin_private *)dev->priv;
-       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+       yp = (struct yellowfin_private *)dev->priv;
+       if (test_and_set_bit(0, (void*)&yp->in_interrupt)) {
+               dev->interrupt = 1;
                printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
                return;
        }
 
        do {
                u16 intr_status = inw(ioaddr + IntrClear);
-               unsigned dirty_tx = lp->dirty_tx;
 
                if (yellowfin_debug > 4)
-                       printk("%s: Yellowfin interrupt, status %4.4x.\n",
+                       printk(KERN_DEBUG "%s: Yellowfin interrupt, status %4.4x.\n",
                                   dev->name, intr_status);
 
                if (intr_status == 0)
                        break;
 
-               if (intr_status & (IntrRxDone | IntrEarlyRx))
+               if (intr_status & (IntrRxDone | IntrEarlyRx)) {
                        yellowfin_rx(dev);
+                       outl(0x10001000, ioaddr + RxCtrl);              /* Wake Rx engine. */
+               }
 
 #ifdef NO_TXSTATS
-               for (; dirty_tx < lp->cur_tx; dirty_tx++) {
-                       int entry = dirty_tx % TX_RING_SIZE;
-                       if (lp->tx_ring[entry].status == 0)
+               for (; yp->cur_tx - yp->dirty_tx > 0; yp->dirty_tx++) {
+                       int entry = yp->dirty_tx % TX_RING_SIZE;
+                       if (yp->tx_ring[entry].status == 0)
                                break;
                        /* Free the original skb. */
-                       dev_kfree_skb(lp->tx_skbuff[entry]);
-                       lp->tx_skbuff[entry] = 0;
-                       lp->stats.tx_packets++;
+                       DEV_FREE_SKB(yp->tx_skbuff[entry]);
+                       yp->tx_skbuff[entry] = 0;
+                       yp->stats.tx_packets++;
                }
-               if (lp->tx_full && dev->tbusy
-                       && dirty_tx > lp->cur_tx - TX_RING_SIZE + 4) {
+               if (yp->tx_full && dev->tbusy
+                       && yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) {
                        /* The ring is no longer full, clear tbusy. */
-                       lp->tx_full = 0;
-                       dev->tbusy = 0;
+                       yp->tx_full = 0;
+                       clear_bit(0, (void*)&dev->tbusy);
                        mark_bh(NET_BH);
                }
-               lp->dirty_tx = dirty_tx;
 #else
                if (intr_status & IntrTxDone
-                       || lp->tx_status[dirty_tx % TX_RING_SIZE].tx_errs) {
+                       || yp->tx_tail_desc->tx_errs) {
+                       unsigned dirty_tx = yp->dirty_tx;
 
-                       for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+                       for (dirty_tx = yp->dirty_tx; yp->cur_tx - dirty_tx > 0;
+                                dirty_tx++) {
                                /* Todo: optimize this. */
                                int entry = dirty_tx % TX_RING_SIZE;
-                               u16 tx_errs = lp->tx_status[entry].tx_errs;
+                               u16 tx_errs = yp->tx_status[entry].tx_errs;
 
+#ifndef final_version
+                               if (yellowfin_debug > 5)
+                                       printk(KERN_DEBUG "%s: Tx queue %d check, Tx status "
+                                                  "%4.4x %4.4x %4.4x %4.4x.\n",
+                                                  dev->name, entry,
+                                                  yp->tx_status[entry].tx_cnt,
+                                                  yp->tx_status[entry].tx_errs,
+                                                  yp->tx_status[entry].total_tx_cnt,
+                                                  yp->tx_status[entry].paused);
+#endif
                                if (tx_errs == 0)
                                        break;                  /* It still hasn't been Txed */
                                if (tx_errs & 0xF8100000) {
                                        /* There was an major error, log it. */
 #ifndef final_version
                                        if (yellowfin_debug > 1)
-                                               printk("%s: Transmit error, Tx status %4.4x.\n",
+                                               printk(KERN_DEBUG "%s: Transmit error, Tx status %4.4x.\n",
                                                           dev->name, tx_errs);
 #endif
-                                       lp->stats.tx_errors++;
-                                       if (tx_errs & 0xF800) lp->stats.tx_aborted_errors++;
-                                       if (tx_errs & 0x0800) lp->stats.tx_carrier_errors++;
-                                       if (tx_errs & 0x2000) lp->stats.tx_window_errors++;
-                                       if (tx_errs & 0x8000) lp->stats.tx_fifo_errors++;
+                                       yp->stats.tx_errors++;
+                                       if (tx_errs & 0xF800) yp->stats.tx_aborted_errors++;
+                                       if (tx_errs & 0x0800) yp->stats.tx_carrier_errors++;
+                                       if (tx_errs & 0x2000) yp->stats.tx_window_errors++;
+                                       if (tx_errs & 0x8000) yp->stats.tx_fifo_errors++;
 #ifdef ETHER_STATS
-                                       if (tx_errs & 0x1000) lp->stats.collisions16++;
+                                       if (tx_errs & 0x1000) yp->stats.collisions16++;
 #endif
                                } else {
+#ifndef final_version
+                                       if (yellowfin_debug > 4)
+                                               printk(KERN_DEBUG "%s: Normal transmit, Tx status %4.4x.\n",
+                                                          dev->name, tx_errs);
+#endif
 #ifdef ETHER_STATS
-                                       if (status & 0x0400) lp->stats.tx_deferred++;
+                                       if (tx_errs & 0x0400) yp->stats.tx_deferred++;
 #endif
-                                       lp->stats.collisions += tx_errs & 15;
-                                       lp->stats.tx_packets++;
+                                       yp->stats.collisions += tx_errs & 15;
+                                       yp->stats.tx_packets++;
                                }
 
                                /* Free the original skb. */
-                               dev_kfree_skb(lp->tx_skbuff[entry]);
-                               lp->tx_skbuff[entry] = 0;
+                               DEV_FREE_SKB(yp->tx_skbuff[entry]);
+                               yp->tx_skbuff[entry] = 0;
                                /* Mark status as empty. */
-                               lp->tx_status[entry].tx_errs = 0;
+                               yp->tx_status[entry].tx_errs = 0;
                        }
 
 #ifndef final_version
-                       if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
-                               printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-                                          dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+                       if (yp->cur_tx - dirty_tx > TX_RING_SIZE) {
+                               printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+                                          dev->name, dirty_tx, yp->cur_tx, yp->tx_full);
                                dirty_tx += TX_RING_SIZE;
                        }
 #endif
 
-                       if (lp->tx_full && dev->tbusy
-                               && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+                       if (yp->tx_full && dev->tbusy
+                               && yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
                                /* The ring is no longer full, clear tbusy. */
-                               lp->tx_full = 0;
-                               dev->tbusy = 0;
+                               yp->tx_full = 0;
+                               clear_bit(0, (void*)&dev->tbusy);
                                mark_bh(NET_BH);
                        }
 
-                       lp->dirty_tx = dirty_tx;
+                       yp->dirty_tx = dirty_tx;
+                       yp->tx_tail_desc = &yp->tx_status[dirty_tx % TX_RING_SIZE];
                }
 #endif
 
-               /* Log errors and other events. */
-               if (intr_status & 0x2ee) {      /* Abnormal error summary. */
-                       printk("%s: Something Wicked happened! %4.4x.\n",
-                                  dev->name, intr_status);
-                       /* Hmmmmm, it's not clear what to do here. */
-                       if (intr_status & (IntrTxPCIErr | IntrTxPCIFault))
-                               lp->stats.tx_errors++;
-                       if (intr_status & (IntrRxPCIErr | IntrRxPCIFault))
-                               lp->stats.rx_errors++;
-               }
+               /* Log errors and other uncommon events. */
+               if (intr_status & 0x2ee)        /* Abnormal error summary. */
+                       yellowfin_error(dev, intr_status);
+
                if (--boguscnt < 0) {
-                       printk("%s: Too much work at interrupt, status=0x%4.4x.\n",
+                       printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n",
                                   dev->name, intr_status);
                        break;
                }
        } while (1);
 
        if (yellowfin_debug > 3)
-               printk("%s: exiting interrupt, status=%#4.4x.\n",
+               printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
                           dev->name, inw(ioaddr + IntrStatus));
 
        /* Code that should never be run!  Perhaps remove after testing.. */
        {
                static int stopit = 10;
                if (dev->start == 0  &&  --stopit < 0) {
-                       printk("%s: Emergency stop, looping startup interrupt.\n",
+                       printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
                                   dev->name);
-#ifdef SA_SHIRQ
                        free_irq(irq, dev);
-#else
-                       free_irq(irq);
-#endif
                }
        }
 
        dev->interrupt = 0;
+       clear_bit(0, (void*)&yp->in_interrupt);
        return;
 }
 
 /* This routine is logically part of the interrupt handler, but separated
    for clarity and better register allocation. */
-static int
-yellowfin_rx(struct device *dev)
+static int yellowfin_rx(struct device *dev)
 {
-       struct yellowfin_private *lp = (struct yellowfin_private *)dev->priv;
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
-       int entry = lp->cur_rx % RX_RING_SIZE;
+       int entry = yp->cur_rx % RX_RING_SIZE;
        int boguscnt = 20;
 
        if (yellowfin_debug > 4) {
-               printk(" In yellowfin_rx(), entry %d status %4.4x.\n", entry,
-                          yp->rx_ring[entry].status);
-               printk("   #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n",
+               printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %4.4x.\n",
+                          entry, yp->rx_ring[entry].status);
+               printk(KERN_DEBUG "   #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n",
                           entry, yp->rx_ring[entry].cmd,
                           yp->rx_ring[entry].request_cnt, yp->rx_ring[entry].addr,
                           yp->rx_ring[entry].result_cnt, yp->rx_ring[entry].status);
        }
 
-
        /* If EOP is set on the next entry, it's a new packet. Send it up. */
-       while (yp->rx_ring[entry].status) {
-               /* Todo: optimize this mess. */
-               u16 desc_status = yp->rx_ring[entry].status;
-               struct yellowfin_desc *desc = &lp->rx_ring[entry];
-               int frm_size = desc->request_cnt - desc->result_cnt;
-               u8 *buf_addr = bus_to_virt(lp->rx_ring[entry].addr);
-               s16 frame_status = *(s16*)&(buf_addr[frm_size - 2]);
+       while (yp->rx_head_desc->status) {
+               struct yellowfin_desc *desc = yp->rx_head_desc;
+               u16 desc_status = desc->status;
+               int data_size = desc->request_cnt - desc->result_cnt;
+               u8 *buf_addr = bus_to_virt(desc->addr);
+               s16 frame_status = *(s16*)&(buf_addr[data_size - 2]); /* ?Alpha safe on 885? */
 
                if (yellowfin_debug > 4)
-                       printk("  yellowfin_rx() status was %4.4x.\n", frame_status);
+                       printk(KERN_DEBUG "  yellowfin_rx() status was %4.4x.\n",
+                                  frame_status);
                if (--boguscnt < 0)
                        break;
                if ( ! (desc_status & RX_EOP)) {
-                       printk("%s: Oversized Ethernet frame spanned multiple buffers,"
+                       printk(KERN_WARNING "%s: Oversized Ethernet frame spanned multiple buffers,"
                                   " status %4.4x!\n", dev->name, desc_status);
-                         lp->stats.rx_length_errors++;
-               } else if (frame_status & 0x0038) {
+                       yp->stats.rx_length_errors++;
+               } else if (yp->chip_id == 0  &&  (frame_status & 0x0038)) {
                        /* There was a error. */
                        if (yellowfin_debug > 3)
-                               printk("  yellowfin_rx() Rx error was %4.4x.\n", frame_status);
-                       lp->stats.rx_errors++;
-                       if (frame_status & 0x0060) lp->stats.rx_length_errors++;
-                       if (frame_status & 0x0008) lp->stats.rx_frame_errors++;
-                       if (frame_status & 0x0010) lp->stats.rx_crc_errors++;
-                       if (frame_status < 0) lp->stats.rx_dropped++;
+                               printk(KERN_DEBUG "  yellowfin_rx() Rx error was %4.4x.\n",
+                                          frame_status);
+                       yp->stats.rx_errors++;
+                       if (frame_status & 0x0060) yp->stats.rx_length_errors++;
+                       if (frame_status & 0x0008) yp->stats.rx_frame_errors++;
+                       if (frame_status & 0x0010) yp->stats.rx_crc_errors++;
+                       if (frame_status < 0) yp->stats.rx_dropped++;
+               } else if (yp->chip_id != 0  &&
+                                  ((buf_addr[data_size-1] & 0x85) || buf_addr[data_size-2] & 0xC0)) {
+                       u8 status1 = buf_addr[data_size-2];
+                       u8 status2 = buf_addr[data_size-1];
+                       yp->stats.rx_errors++;
+                       if (status1 & 0xC0) yp->stats.rx_length_errors++;
+                       if (status2 & 0x03) yp->stats.rx_frame_errors++;
+                       if (status2 & 0x04) yp->stats.rx_crc_errors++;
+                       if (status2 & 0x80) yp->stats.rx_dropped++;
 #ifdef YF_PROTOTYPE                    /* Support for prototype hardware errata. */
-               } else if (memcmp(bus_to_virt(lp->rx_ring[entry].addr),
+               } else if (memcmp(bus_to_virt(yp->rx_ring[entry].addr),
                                                  dev->dev_addr, 6) != 0
-                                  && memcmp(bus_to_virt(lp->rx_ring[entry].addr),
-                                                        "\0377\0377\0377\0377\0377\0377", 6) != 0) {
-                       printk("%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
-                                  dev->name,
-                                  ((char *)bus_to_virt(lp->rx_ring[entry].addr))[0],
-                                  ((char *)bus_to_virt(lp->rx_ring[entry].addr))[1],
-                                  ((char *)bus_to_virt(lp->rx_ring[entry].addr))[2],
-                                  ((char *)bus_to_virt(lp->rx_ring[entry].addr))[3],
-                                  ((char *)bus_to_virt(lp->rx_ring[entry].addr))[4],
-                                  ((char *)bus_to_virt(lp->rx_ring[entry].addr))[5]);
+                                  && memcmp(bus_to_virt(yp->rx_ring[entry].addr),
+                                                        "\377\377\377\377\377\377", 6) != 0) {
+                       printk(KERN_WARNING "%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+                                  dev->name, buf_addr[0], buf_addr[1], buf_addr[2],
+                                  buf_addr[3], buf_addr[4], buf_addr[5]);
                        bogus_rx++;
 #endif
                } else {
-                       u8 bogus_cnt = buf_addr[frm_size - 8];
-                       short pkt_len = frm_size - 8 - bogus_cnt;
                        struct sk_buff *skb;
-                       int rx_in_place = 0;
+                       int pkt_len = data_size -
+                               (yp->chip_id ? 7 : 8 + buf_addr[data_size - 8]);
+                       /* To verify: Yellowfin Length should omit the CRC! */
 
-                       /* Check if the packet is long enough to just accept without
-                          copying to a properly sized skbuff. */
+#ifndef final_version
+                       if (yellowfin_debug > 4)
+                               printk(KERN_DEBUG "  yellowfin_rx() normal Rx pkt length %d"
+                                          " of %d, bogus_cnt %d.\n",
+                                          pkt_len, data_size, boguscnt);
+#endif
+                       /* Check if the packet is long enough to just pass up the skbuff
+                          without copying to a properly sized skbuff. */
                        if (pkt_len > rx_copybreak) {
-                               struct sk_buff *newskb;
-                               char *temp;
-
-                               /* Get a fresh skbuff to replace the filled one. */
-                               newskb = DEV_ALLOC_SKB(dev->mtu <= 1500 ? PKT_BUF_SZ
-                                                                          : dev->mtu + 32);
-                               if (newskb == NULL) {
-                                       skb = 0;                /* No memory, drop the packet. */
-                                       goto memory_squeeze;
-                               }
-                               /* Pass up the skb already on the Rx ring. */
-                               skb = lp->rx_skbuff[entry];
-                               temp = skb_put(skb, pkt_len);
-                               if (bus_to_virt(lp->rx_ring[entry].addr) != temp)
-                                       printk("%s: Warning -- the skbuff addresses do not match"
-                                                  " in yellowfin_rx: %p vs. %p / %p.\n", dev->name,
-                                                  bus_to_virt(lp->rx_ring[entry].addr),
+                               char *temp = skb_put(skb = yp->rx_skbuff[entry], pkt_len);
+#ifndef final_verison                          /* Remove after testing. */
+                               if (bus_to_virt(yp->rx_ring[entry].addr) != temp)
+                                       printk(KERN_WARNING "%s: Warning -- the skbuff addresses "
+                                                  "do not match in yellowfin_rx: %p vs. %p / %p.\n",
+                                                  dev->name, bus_to_virt(yp->rx_ring[entry].addr),
                                                   skb->head, temp);
-                               rx_in_place = 1;
-                               lp->rx_skbuff[entry] = newskb;
-                               newskb->dev = dev;
-                               skb_reserve(newskb, 2); /* 16 byte align IP header */
-                               lp->rx_ring[entry].addr = virt_to_bus(newskb->tail);
-                       } else
-                               skb = DEV_ALLOC_SKB(pkt_len + 2);
-                       memory_squeeze:
-                       if (skb == NULL) {
-                               printk("%s: Memory squeeze, deferring packet.\n", dev->name);
-                               /* todo: Check that at least two ring entries are free.
-                                  If not, free one and mark stats->rx_dropped++. */
-                               break;
-                       }
-                       skb->dev = dev;
-                       if (! rx_in_place) {
+#endif
+                               yp->rx_skbuff[entry] = NULL;
+                       } else {
+                               skb = dev_alloc_skb(pkt_len + 2);
+                               if (skb == NULL)
+                                       break;
+                               skb->dev = dev;
                                skb_reserve(skb, 2);    /* 16 byte align the data fields */
+#if 1
+                               eth_copy_and_sum(skb, bus_to_virt(yp->rx_ring[entry].addr),
+                                                                pkt_len, 0);
+                               skb_put(skb, pkt_len);
+#else
                                memcpy(skb_put(skb, pkt_len),
-                                          bus_to_virt(lp->rx_ring[entry].addr), pkt_len);
+                                          bus_to_virt(yp->rx_ring[entry].addr), pkt_len);
+#endif
                        }
-#if LINUX_VERSION_CODE > 0x10300
                        skb->protocol = eth_type_trans(skb, dev);
-#else
-                       skb->len = pkt_len;
-#endif
                        netif_rx(skb);
-                       lp->stats.rx_packets++;
+                       dev->last_rx = jiffies;
+                       yp->stats.rx_packets++;
                }
+               entry = (++yp->cur_rx) % RX_RING_SIZE;
+               yp->rx_head_desc = &yp->rx_ring[entry];
+       }
 
-               /* Mark this entry as being the end-of-list, and the prior entry
-                  as now valid. */
-               lp->rx_ring[entry].cmd = CMD_STOP;
-               yp->rx_ring[entry].status = 0;
-               {
-                       int prev_entry = entry - 1;
-                       if (prev_entry < 0)
-                               lp->rx_ring[RX_RING_SIZE - 1].cmd =
-                                       CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS;
-                       else
-                               lp->rx_ring[prev_entry].cmd = CMD_RX_BUF | INTR_ALWAYS;
+       /* Refill the Rx ring buffers. */
+       for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) {
+               struct sk_buff *skb;
+               entry = yp->dirty_rx % RX_RING_SIZE;
+               if (yp->rx_skbuff[entry] == NULL) {
+                       skb = dev_alloc_skb(yp->rx_buf_sz);
+                       if (skb == NULL)
+                               break;                  /* Better luck next round. */
+                       skb->dev = dev;                 /* Mark as being used by this device. */
+                       skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+                       yp->rx_ring[entry].addr = virt_to_bus(skb->tail);
+                       yp->rx_skbuff[entry] = skb;
                }
-               entry = (++lp->cur_rx) % RX_RING_SIZE;
+               yp->rx_ring[entry].cmd = CMD_STOP;
+               yp->rx_ring[entry].status = 0;  /* Clear complete bit. */
+               if (entry != 0)
+                       yp->rx_ring[entry - 1].cmd = CMD_RX_BUF | INTR_ALWAYS;
+               else
+                       yp->rx_ring[RX_RING_SIZE - 1].cmd =
+                               CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS;
        }
-       /* todo: restart Rx engine if stopped.  For now we just make the Rx ring
-          large enough to avoid this. */
 
        return 0;
 }
 
-static int
-yellowfin_close(struct device *dev)
+static void yellowfin_error(struct device *dev, int intr_status)
 {
-       int ioaddr = dev->base_addr;
+       struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+
+       printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
+                  dev->name, intr_status);
+       /* Hmmmmm, it's not clear what to do here. */
+       if (intr_status & (IntrTxPCIErr | IntrTxPCIFault))
+               yp->stats.tx_errors++;
+       if (intr_status & (IntrRxPCIErr | IntrRxPCIFault))
+               yp->stats.rx_errors++;
+}
+
+static int yellowfin_close(struct device *dev)
+{
+       long ioaddr = dev->base_addr;
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
        int i;
 
@@ -1096,10 +1204,10 @@ yellowfin_close(struct device *dev)
        dev->tbusy = 1;
 
        if (yellowfin_debug > 1) {
-               printk("%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
+               printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
                           dev->name, inw(ioaddr + TxStatus),
-                          inw(ioaddr + RxStatus), inl(ioaddr + IntrStatus));
-               printk("%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",
+                          inw(ioaddr + RxStatus), inw(ioaddr + IntrStatus));
+               printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",
                           dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx);
        }
 
@@ -1112,8 +1220,9 @@ yellowfin_close(struct device *dev)
 
        del_timer(&yp->timer);
 
+#ifdef __i386__
        if (yellowfin_debug > 2) {
-               printk("\n  Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring));
+               printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring));
                for (i = 0; i < TX_RING_SIZE*2; i++)
                        printk(" %c #%d desc. %4.4x %4.4x %8.8x %8.8x %4.4x %4.4x.\n",
                                   inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
@@ -1121,20 +1230,20 @@ yellowfin_close(struct device *dev)
                                   yp->tx_ring[i].request_cnt, yp->tx_ring[i].addr,
                                   yp->tx_ring[i].branch_addr,
                                   yp->tx_ring[i].result_cnt, yp->tx_ring[i].status);
-               printk("  Tx status %p:\n", yp->tx_status);
+               printk(KERN_DEBUG "  Tx status %p:\n", yp->tx_status);
                for (i = 0; i < TX_RING_SIZE; i++)
                        printk("   #%d status %4.4x %4.4x %4.4x %4.4x.\n",
                                   i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs,
                                   yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused);
 
-               printk("\n  Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring));
+               printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring));
                for (i = 0; i < RX_RING_SIZE; i++) {
-                       printk(" %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n",
+                       printk(KERN_DEBUG " %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n",
                                   inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
                                   i, yp->rx_ring[i].cmd,
                                   yp->rx_ring[i].request_cnt, yp->rx_ring[i].addr,
                                   yp->rx_ring[i].result_cnt, yp->rx_ring[i].status);
-                       if (yellowfin_debug > 5) {
+                       if (yellowfin_debug > 6) {
                                if (*(u8*)yp->rx_ring[i].addr != 0x69) {
                                        int j;
                                        for (j = 0; j < 0x50; j++)
@@ -1144,13 +1253,9 @@ yellowfin_close(struct device *dev)
                        }
                }
        }
+#endif /* __i386__ debugging only */
 
-#ifdef SA_SHIRQ
        free_irq(dev->irq, dev);
-#else
-       free_irq(dev->irq);
-       irq2dev_map[dev->irq] = 0;
-#endif
 
        /* Free all the skbuffs in the Rx queue. */
        for (i = 0; i < RX_RING_SIZE; i++) {
@@ -1160,19 +1265,19 @@ yellowfin_close(struct device *dev)
 #if LINUX_VERSION_CODE < 0x20100
                        yp->rx_skbuff[i]->free = 1;
 #endif
-                       dev_kfree_skb(yp->rx_skbuff[i]);
+                       DEV_FREE_SKB(yp->rx_skbuff[i]);
                }
                yp->rx_skbuff[i] = 0;
        }
        for (i = 0; i < TX_RING_SIZE; i++) {
                if (yp->tx_skbuff[i])
-                       dev_kfree_skb(yp->tx_skbuff[i]);
+                       DEV_FREE_SKB(yp->tx_skbuff[i]);
                yp->tx_skbuff[i] = 0;
        }
 
 #ifdef YF_PROTOTYPE                    /* Support for prototype hardware errata. */
        if (yellowfin_debug > 0) {
-               printk("%s: Received %d frames that we should not have.\n",
+               printk(KERN_DEBUG "%s: Received %d frames that we should not have.\n",
                           dev->name, bogus_rx);
        }
 #endif
@@ -1181,8 +1286,7 @@ yellowfin_close(struct device *dev)
        return 0;
 }
 
-static struct enet_statistics *
-yellowfin_get_stats(struct device *dev)
+static struct enet_statistics *yellowfin_get_stats(struct device *dev)
 {
        struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
        return &yp->stats;
@@ -1194,6 +1298,7 @@ yellowfin_get_stats(struct device *dev)
    N.B. Do not use for bulk data, use a table-based routine instead.
    This is common code and should be moved to net/core/crc.c */
 static unsigned const ethernet_polynomial_le = 0xedb88320U;
+
 static inline unsigned ether_crc_le(int length, unsigned char *data)
 {
        unsigned int crc = 0xffffffff;  /* Initial value. */
@@ -1212,25 +1317,20 @@ static inline unsigned ether_crc_le(int length, unsigned char *data)
 }
 
 
-static void
-#ifdef NEW_MULTICAST
-set_rx_mode(struct device *dev)
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_rx_mode(struct device *dev)
 {
-       int ioaddr = dev->base_addr;
+       struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+       long ioaddr = dev->base_addr;
        u16 cfg_value = inw(ioaddr + Cnfg);
 
        /* Stop the Rx process to change any value. */
        outw(cfg_value & ~0x1000, ioaddr + Cnfg);
        if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous. */
                /* Unconditionally log net taps. */
-               printk("%s: Promiscuous mode enabled.\n", dev->name);
+               printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
                outw(0x000F, ioaddr + AddrMode);
        } else if ((dev->mc_count > 64)  ||  (dev->flags & IFF_ALLMULTI)) {
                /* Too many to filter well, or accept all multicasts. */
-               printk("%s: Set all-multicast mode.\n", dev->name);
                outw(0x000B, ioaddr + AddrMode);
        } else if (dev->mc_count > 0) { /* Must use the multicast hash table. */
                struct dev_mc_list *mclist;
@@ -1241,49 +1341,67 @@ static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
                         i++, mclist = mclist->next) {
                        /* Due to a bug in the early chip versions, multiple filter
                           slots must be set for each address. */
-                       set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f,
-                                       hash_table);
-                       set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f,
-                                       hash_table);
-                       set_bit((ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f,
-                                       hash_table);
+                       if (yp->chip_id == 0) {
+                               set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f,
+                                               hash_table);
+                               set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f,
+                                               hash_table);
+                               set_bit((ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f,
+                                               hash_table);
+                       }
                        set_bit((ether_crc_le(6, mclist->dmi_addr) >> 3) & 0x3f,
                                        hash_table);
                }
                /* Copy the hash table to the chip. */
                for (i = 0; i < 4; i++)
                        outw(hash_table[i], ioaddr + HashTbl + i*2);
-               printk("%s: Set multicast mode.\n", dev->name);
                outw(0x0003, ioaddr + AddrMode);
        } else {                                        /* Normal, unicast/broadcast-only mode. */
-               printk("%s: Set unicast mode.\n", dev->name);
                outw(0x0001, ioaddr + AddrMode);
        }
        /* Restart the Rx process. */
        outw(cfg_value | 0x1000, ioaddr + Cnfg);
 }
+
+#ifdef HAVE_PRIVATE_IOCTL
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+       long ioaddr = dev->base_addr;
+       u16 *data = (u16 *)&rq->ifr_data;
+
+       switch(cmd) {
+       case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
+               data[0] = ((struct yellowfin_private *)dev->priv)->phys[0] & 0x1f;
+               /* Fall Through */
+       case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
+               data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+               return 0;
+       case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
+               if (!suser())
+                       return -EPERM;
+               mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+#endif  /* HAVE_PRIVATE_IOCTL */
+
 \f
 #ifdef MODULE
 
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 
-int
-init_module(void)
+int init_module(void)
 {
-       int cards_found;
-
        if (debug >= 0)
                yellowfin_debug = debug;
 
-       root_yellowfin_dev = NULL;
-       cards_found = yellowfin_probe(0);
-
-       return cards_found ? 0 : -ENODEV;
+       return yellowfin_probe(0);
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
        struct device *next_dev;
 
@@ -1301,7 +1419,9 @@ cleanup_module(void)
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  compile-command-alphaLX: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`  -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
index 5eff1c110ef9bd9f4f809d2579bfb0c59fd7dedd..26cf57793a6aad883c710d8066a003b04d02a1cc 100644 (file)
@@ -391,9 +391,12 @@ static void z8530_dma_rx(struct z8530_channel *chan)
        if(chan->rxdma_on)
        {
                /* Special condition check only */
-               u8 r7=read_zsreg(chan, R7);
-               u8 r6=read_zsreg(chan, R6);
-               u8 status=read_zsreg(chan, R1);
+               u8 status;
+
+               read_zsreg(chan, R7);
+               read_zsreg(chan, R6);
+               
+               status=read_zsreg(chan, R1);
                if(status&END_FR)
                {
                        z8530_rx_done(chan);    /* Fire up the next one */
index 595c301f633974f3a6f2422c752f713ce764450e..0297d8b0f7c6cac63cc4b58fb58789c69f266c6a 100644 (file)
@@ -28,8 +28,10 @@ EXPORT_SYMBOL(pci_find_class);
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_slot);
 EXPORT_SYMBOL(pci_set_master);
+#ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_device);
+#endif
 
 /* Backward compatibility */
 
index 34a0bbbb04c692ed7b024c2f0098b475c0b127de..2cfe9a6e73d89bdd35e279f1e70a55ff89c08e9e 100644 (file)
@@ -48,6 +48,11 @@ dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) supp
     int  '  maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
   fi
 dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
+if [ "$CONFIG_MCA" = "y" ]; then
+  if [ "$CONFIG_SCSI" = "y" ]; then
+    bool 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS
+  fi
+fi
 dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
 dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_PARPORT" != "n" ]; then
index 2e43edb8b5b1fc9fe6f87d80328656c93a46c015..f3be0cf18015dcebc95f8f3d3787a0bd1b3ad2d5 100644 (file)
@@ -486,6 +486,11 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_FD_MCS),y)
+L_OBJS += fd_mcs.o
+endif
+
+
 ifeq ($(CONFIG_SCSI_T128),y)
 L_OBJS += t128.o
 else
index 4f7227875ec89be04db6b16832f8088dd4475395..078b64ae6dab2adf7b8c26240a8ac70e5d642701 100644 (file)
  * #define AIC7XXX_VERBOSE_DEBUGGING
  */
  
-#ifdef MODULE
+#if defined(MODULE) || defined(PCMCIA)
 #include <linux/module.h>
 #endif
 
+#if defined(PCMCIA)
+#  undef MODULE
+#endif
+
 #include <stdarg.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/byteorder.h>
 #include <linux/version.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -349,7 +354,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.3"
+#define AIC7XXX_C_VERSION  "5.1.4"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -683,12 +688,14 @@ struct seeprom_config {
 #define CFDISC                0x0010      /* enable disconnection */
 #define CFWIDEB               0x0020      /* wide bus device (wide card) */
 #define CFSYNCHISULTRA        0x0040      /* CFSYNC is an ultra offset */
-/* UNUSED                0x0080 */
+#define CFNEWULTRAFORMAT      0x0080      /* Use the Ultra2 SEEPROM format */
 #define CFSTART               0x0100      /* send start unit SCSI command */
 #define CFINCBIOS             0x0200      /* include in BIOS scan */
 #define CFRNFOUND             0x0400      /* report even if not found */
 #define CFMULTILUN            0x0800      /* probe mult luns in BIOS scan */
-/* UNUSED                0xF000 */
+#define CFWBCACHEYES          0x4000      /* Enable W-Behind Cache on drive */
+#define CFWBCACHENC           0xc000      /* Don't change W-Behind Cache */
+/* UNUSED                0x3000 */
   unsigned short device_flags[16];        /* words 0-15 */
 
 /*
@@ -1481,8 +1488,8 @@ static int aic7xxx_verbose = VERBOSE_NORMAL | VERBOSE_NEGOTIATION |
 static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd);
 static void aic7xxx_print_card(struct aic7xxx_host *p);
 static void aic7xxx_print_scratch_ram(struct aic7xxx_host *p);
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
 static void aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
 static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);
 #endif
 
@@ -1544,26 +1551,6 @@ aic_outb(struct aic7xxx_host *p, unsigned char val, long port)
 #endif
 }
 
-static void
-aic_outsb(struct aic7xxx_host *p, long port, unsigned char *valp, size_t size)
-{
-#ifdef MMAPIO
-  if(p->maddr)
-  {
-    int i;
-    for (i=0; i < size; i++)
-    {
-      p->maddr[port] = valp[i];
-    }
-    mb();
-  }
-  else
-    outsb(p->base + port, valp, size);
-#else
-  outsb(p->base + port, valp, size);
-#endif
-}
-
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_setup
@@ -1752,7 +1739,9 @@ unpause_sequencer(struct aic7xxx_host *p, int unpause_always)
 static inline void
 restart_sequencer(struct aic7xxx_host *p)
 {
-  aic_outb(p, FASTMODE|SEQRESET, SEQCTL);
+  aic_outb(p, 0, SEQADDR0);
+  aic_outb(p, 0, SEQADDR1);
+  aic_outb(p, FASTMODE, SEQCTL);
 }
 
 /*
@@ -1831,6 +1820,8 @@ aic7xxx_download_instr(struct aic7xxx_host *p, int instrptr,
 
   instr = *(union ins_formats*) &seqprog[instrptr * 4];
 
+  instr.integer = le32_to_cpu(instr.integer);
+  
   fmt1_ins = &instr.format1;
   fmt3_ins = NULL;
 
@@ -1926,7 +1917,10 @@ aic7xxx_download_instr(struct aic7xxx_host *p, int instrptr,
                           (fmt1_ins->opcode << 25);
         }
       }
-      aic_outsb(p, SEQRAM, instr.bytes, 4);
+      aic_outb(p, (instr.integer & 0xff), SEQRAM);
+      aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM);
+      aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM);
+      aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM);
       break;
 
     default:
@@ -1976,18 +1970,21 @@ aic7xxx_loadseq(struct aic7xxx_host *p)
     downloaded++;
   }
 
-  aic_outb(p, FASTMODE|SEQRESET, SEQCTL);
+  aic_outb(p, 0, SEQADDR0);
+  aic_outb(p, 0, SEQADDR1);
+  aic_outb(p, FASTMODE | FAILDIS, SEQCTL);
+  unpause_sequencer(p, TRUE);
+  mdelay(1);
+  pause_sequencer(p);
+  aic_outb(p, FASTMODE, SEQCTL);
   if (aic7xxx_verbose & VERBOSE_PROBE)
   {
     printk(" %d instructions downloaded\n", downloaded);
   }
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
   if (aic7xxx_dump_sequencer)
     aic7xxx_print_sequencer(p, downloaded);
-#endif
 }
 
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_print_sequencer
@@ -2022,10 +2019,15 @@ aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded)
     else
       printk(" ");
   }
-  aic_outb(p, FASTMODE|SEQRESET, SEQCTL);
+  aic_outb(p, 0, SEQADDR0);
+  aic_outb(p, 0, SEQADDR1);
+  aic_outb(p, FASTMODE | FAILDIS, SEQCTL);
+  unpause_sequencer(p, TRUE);
+  mdelay(1);
+  pause_sequencer(p);
+  aic_outb(p, FASTMODE, SEQCTL);
   printk("\n");
 }
-#endif
 
 /*+F*************************************************************************
  * Function:
@@ -4147,8 +4149,10 @@ aic7xxx_timer(struct aic7xxx_host *p)
 #endif
   for(i=0; i<MAX_TARGETS; i++)
   {
-    if ( del_timer(&p->dev_timer[i]) )
+    if ( timer_pending(&p->dev_timer[i]) && 
+         time_before_eq(p->dev_timer[i].expires, jiffies) )
     {
+      del_timer(&p->dev_timer[i]);
       p->dev_temp_queue_depth[i] =  p->dev_max_queue_depth[i];
       j = 0;
       while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) &&
@@ -5498,7 +5502,7 @@ aic7xxx_handle_reqinit(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
 {
   unsigned char lastbyte;
   unsigned char phasemis;
-  int done;
+  int done = FALSE;
 
   switch(p->msg_type)
   {
@@ -7548,6 +7552,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
       p->host_no, p->mbase, (unsigned long)p->maddr);
   }
 
+#ifdef CONFIG_PCI
   /*
    * Now that we know our instance number, we can set the flags we need to
    * force termination if need be.
@@ -7587,6 +7592,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
 #endif
     }
   }
+#endif
 
   /*
    * That took care of devconfig and stpwlev, now for the actual termination
@@ -7637,19 +7643,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
     }
   }
 
-  /*
-   * Load the sequencer program, then re-enable the board -
-   * resetting the AIC-7770 disables it, leaving the lights
-   * on with nobody home.
-   */
-  aic7xxx_loadseq(p);
-
-  if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 )
-  {
-    aic_outb(p, ENABLE, BCTL);  /* Enable the boards BUS drivers. */
-  }
-  aic_outb(p, aic_inb(p, SBLKCTL) & ~AUTOFLUSHDIS, SBLKCTL);
-
   /*
    * Clear out any possible pending interrupts.
    */
@@ -7852,6 +7845,18 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
    */
   aic7xxx_allocate_scb(p);
 
+  /*
+   * Load the sequencer program, then re-enable the board -
+   * resetting the AIC-7770 disables it, leaving the lights
+   * on with nobody home.
+   */
+  aic7xxx_loadseq(p);
+
+  if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 )
+  {
+    aic_outb(p, ENABLE, BCTL);  /* Enable the boards BUS drivers. */
+  }
+
   if ( !(aic7xxx_no_reset) )
   {
     if (p->features & AHC_TWIN)
@@ -8254,9 +8259,10 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
   {
     for (i = 0; i < max_targets; i++)
     {
-      if( (p->features & AHC_ULTRA) &&
-         !(sc->adapter_control & CFULTRAEN) &&
-          (sc->device_flags[i] & CFSYNCHISULTRA) )
+      if( ((p->features & AHC_ULTRA) &&
+          !(sc->adapter_control & CFULTRAEN) &&
+           (sc->device_flags[i] & CFSYNCHISULTRA)) ||
+          (sc->device_flags[i] & CFNEWULTRAFORMAT) )
       {
         p->flags |= AHC_NEWEEPROM_FMT;
         break;
@@ -8333,6 +8339,15 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
       {
         p->ultraenb |= mask;
       }
+      else if (sc->device_flags[i] & CFNEWULTRAFORMAT)
+      {
+        if ( (sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03 )
+        {
+          sc->device_flags[i] &= ~CFXFER;
+          sc->device_flags[i] |= CFSYNCHISULTRA;
+          p->ultraenb |= mask;
+        }
+      }
     }
     else if (sc->adapter_control & CFULTRAEN)
     {
@@ -8480,8 +8495,10 @@ aic7xxx_detect(Scsi_Host_Template *template)
   struct aic7xxx_host *current_p = NULL;
   struct aic7xxx_host *list_p = NULL;
   int found = 0;
+#if defined(__i386__) || defined(__alpha__)
   ahc_flag_type flags = 0;
   int type;
+#endif
   unsigned char sxfrctl1;
 #if defined(__i386__) || defined(__alpha__)
   unsigned char hcntrl, hostconf;
index 669e1b88daf6ce7e01045e6443c42c8668b8a9ea..f55c002dcf2b56e511bc83c899acd94983451c01 100644 (file)
  *      $Id: sequencer.h,v 1.3 1997/09/27 19:37:31 gibbs Exp $
  */
 
+#ifdef __LITTLE_ENDIAN_BITFIELD
 struct ins_format1 {
-       unsigned int    immediate       : 8,
+       unsigned int
+                       immediate       : 8,
                        source          : 9,
                        destination     : 9,
                        ret             : 1,
@@ -46,7 +48,8 @@ struct ins_format1 {
 };
 
 struct ins_format2 {
-       unsigned int    shift_control   : 8,
+       unsigned int
+                       shift_control   : 8,
                        source          : 9,
                        destination     : 9,
                        ret             : 1,
@@ -55,12 +58,43 @@ struct ins_format2 {
 };
 
 struct ins_format3 {
-       unsigned int    immediate       : 8,
+       unsigned int
+                       immediate       : 8,
                        source          : 9,
                        address         : 10,
                        opcode          : 4,
                        parity          : 1;
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+struct ins_format1 {
+       unsigned int
+                       parity          : 1,
+                       opcode          : 4,
+                       ret             : 1,
+                       destination     : 9,
+                       source          : 9,
+                       immediate       : 8;
+};
+
+struct ins_format2 {
+       unsigned int
+                       parity          : 1,
+                       opcode          : 4,
+                       ret             : 1,
+                       destination     : 9,
+                       source          : 9,
+                       shift_control   : 8;
+};
+
+struct ins_format3 {
+       unsigned int
+                       parity          : 1,
+                       opcode          : 4,
+                       address         : 10,
+                       source          : 9,
+                       immediate       : 8;
+};
+#endif
 
 union ins_formats {
                struct ins_format1 format1;
index ea6f716b9ef00c71e0149f7a720a95599115b724..1bfd4a898ca3339d65b1b05497a6107fef85a607 100644 (file)
@@ -50,7 +50,7 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
 
 volatile unsigned char cmd_buffer[16];
                                /* This is where all commands are put
-                                * before they are trasfered to the ESP chip
+                                * before they are transfered to the ESP chip
                                 * via PIO.
                                 */
 
index 58cf54b47dd35e606b18e0d33231ab8880832a6c..b1398d5ea908be3ee1783a660f501fc8557fd402 100644 (file)
@@ -50,7 +50,7 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
 
 volatile unsigned char cmd_buffer[16];
                                /* This is where all commands are put
-                                * before they are trasfered to the ESP chip
+                                * before they are transfered to the ESP chip
                                 * via PIO.
                                 */
 
index 3a0a64c3dcf4212494f39dee889f7d8ea220b11a..e59bb49c45d268d8ee0abbc968f448644776875c 100644 (file)
@@ -59,7 +59,7 @@ static unsigned char ctrl_data = 0;   /* Keep backup of the stuff written
 
 volatile unsigned char cmd_buffer[16];
                                /* This is where all commands are put
-                                * before they are trasfered to the ESP chip
+                                * before they are transfered to the ESP chip
                                 * via PIO.
                                 */
 
index 0ec75eee9372003cadd194fb4294b5f288baec59..d6de03cd7f090c50e64908d9aef25961d1b96083 100644 (file)
@@ -72,7 +72,7 @@ static unsigned char ctrl_data = 0;   /* Keep backup of the stuff written
 
 volatile unsigned char cmd_buffer[16];
                                /* This is where all commands are put
-                                * before they are trasfered to the ESP chip
+                                * before they are transfered to the ESP chip
                                 * via PIO.
                                 */
 
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
new file mode 100644 (file)
index 0000000..3ce90a6
--- /dev/null
@@ -0,0 +1,1481 @@
+/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver
+ *
+ * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net)
+ *
+ * This driver is cloned from fdomain.* to specifically support
+ * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s
+ * also equipped with IBM Fast SCSI Adapter/A which is an OEM
+ * of MCS 700.
+ *
+ * This driver also supports Reply SB16/SCSI card (the SCSI part).
+ *
+ * What makes this driver different is that this driver is MCA only
+ * and it supports multiple adapters in the same system, IRQ 
+ * sharing, some driver statistics, and maps highest SCSI id to sda.
+ * All cards are auto-detected.
+ *
+ * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4
+ *
+ * LILO command-line options:
+ *   fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>]
+ *
+ * ********************************************************
+ * Please see Copyrights/Comments in fdomain.* for credits.
+ * Following is from fdomain.c for acknowledgement:
+ *
+ * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
+ * Revised: Wed Oct  2 11:10:55 1996 by r.faith@ieee.org
+ * Author: Rickard E. Faith, faith@cs.unc.edu
+ * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
+ *
+ * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ **************************************************************************
+
+ NOTES ON USER DEFINABLE OPTIONS:
+
+ DEBUG: This turns on the printing of various debug information.
+
+ ENABLE_PARITY: This turns on SCSI parity checking.  With the current
+ driver, all attached devices must support SCSI parity.  If none of your
+ devices support parity, then you can probably get the driver to work by
+ turning this option off.  I have no way of testing this, however, and it
+ would appear that no one ever uses this option.
+
+ FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
+ 18C30 chip have a 2k cache).  When this many 512 byte blocks are filled by
+ the SCSI device, an interrupt will be raised.  Therefore, this could be as
+ low as 0, or as high as 16.  Note, however, that values which are too high
+ or too low seem to prevent any interrupts from occurring, and thereby lock
+ up the machine.  I have found that 2 is a good number, but throughput may
+ be increased by changing this value to values which are close to 2.
+ Please let me know if you try any different values.
+ [*****Now a runtime option*****]
+
+ RESELECTION: This is no longer an option, since I gave up trying to
+ implement it in version 4.x of this driver.  It did not improve
+ performance at all and made the driver unstable (because I never found one
+ of the two race conditions which were introduced by the multiple
+ outstanding command code).  The instability seems a very high price to pay
+ just so that you don't have to wait for the tape to rewind.  If you want
+ this feature implemented, send me patches.  I'll be happy to send a copy
+ of my (broken) driver to anyone who would like to see a copy.
+
+ **************************************************************************/
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <linux/sched.h>
+#include <linux/blk.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/mca.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "fd_mcs.h"
+
+#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
+
+struct proc_dir_entry proc_scsi_fd_mcs = {
+  PROC_SCSI_FD_MCS, 6, "fd_mcs",
+  S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+  
+/* START OF USER DEFINABLE OPTIONS */
+
+#define DEBUG            0     /* Enable debugging output */
+#define ENABLE_PARITY    1     /* Enable SCSI Parity */
+#define DO_DETECT        0     /* Do device detection here (see scsi.c) */
+
+/* END OF USER DEFINABLE OPTIONS */
+
+#if DEBUG
+#define EVERY_ACCESS     0     /* Write a line on every scsi access */
+#define ERRORS_ONLY      1     /* Only write a line if there is an error */
+#define DEBUG_DETECT     1     /* Debug fd_mcs_detect() */
+#define DEBUG_MESSAGES   1     /* Debug MESSAGE IN phase */
+#define DEBUG_ABORT      1     /* Debug abort() routine */
+#define DEBUG_RESET      1     /* Debug reset() routine */
+#define DEBUG_RACE       1      /* Debug interrupt-driven race condition */
+#else
+#define EVERY_ACCESS     0     /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
+#define ERRORS_ONLY      0
+#define DEBUG_DETECT     0
+#define DEBUG_MESSAGES   0
+#define DEBUG_ABORT      0
+#define DEBUG_RESET      0
+#define DEBUG_RACE       0
+#endif
+
+/* Errors are reported on the line, so we don't need to report them again */
+#if EVERY_ACCESS
+#undef ERRORS_ONLY
+#define ERRORS_ONLY      0
+#endif
+
+#if ENABLE_PARITY
+#define PARITY_MASK      0x08
+#else
+#define PARITY_MASK      0x00
+#endif
+
+enum chip_type {
+  unknown          = 0x00,
+  tmc1800          = 0x01,
+  tmc18c50         = 0x02,
+  tmc18c30         = 0x03,
+};
+
+enum {
+  in_arbitration   = 0x02,
+  in_selection     = 0x04,
+  in_other         = 0x08,
+  disconnect       = 0x10,
+  aborted          = 0x20,
+  sent_ident       = 0x40,
+};
+
+enum in_port_type {
+  Read_SCSI_Data   =  0,
+  SCSI_Status      =  1,
+  TMC_Status       =  2,
+  FIFO_Status      =  3,       /* tmc18c50/tmc18c30 only */
+  Interrupt_Cond   =  4,       /* tmc18c50/tmc18c30 only */
+  LSB_ID_Code      =  5,
+  MSB_ID_Code      =  6,
+  Read_Loopback    =  7,
+  SCSI_Data_NoACK  =  8,
+  Interrupt_Status =  9,
+  Configuration1   = 10,
+  Configuration2   = 11,       /* tmc18c50/tmc18c30 only */
+  Read_FIFO        = 12,
+  FIFO_Data_Count  = 14
+};
+
+enum out_port_type {
+  Write_SCSI_Data  =  0,
+  SCSI_Cntl        =  1,
+  Interrupt_Cntl   =  2,
+  SCSI_Mode_Cntl   =  3,
+  TMC_Cntl         =  4,
+  Memory_Cntl      =  5,       /* tmc18c50/tmc18c30 only */
+  Write_Loopback   =  7,
+  IO_Control       = 11,       /* tmc18c30 only */
+  Write_FIFO       = 12
+};
+
+struct fd_hostdata {
+  unsigned long     _bios_base;
+  int               _bios_major;
+  int               _bios_minor;
+  volatile int      _in_command;
+  Scsi_Cmnd         *_current_SC;
+  enum chip_type    _chip;
+  int               _adapter_mask;
+  int               _fifo_count; /* Number of 512 byte blocks before INTR */
+
+  char              _adapter_name[64];
+#if DEBUG_RACE
+  volatile int      _in_interrupt_flag;
+#endif
+
+  int               _SCSI_Mode_Cntl_port;
+  int               _FIFO_Data_Count_port;
+  int               _Interrupt_Cntl_port;
+  int               _Interrupt_Status_port;
+  int               _Interrupt_Cond_port;
+  int               _Read_FIFO_port;
+  int               _Read_SCSI_Data_port;
+  int               _SCSI_Cntl_port;
+  int               _SCSI_Data_NoACK_port;
+  int               _SCSI_Status_port;
+  int               _TMC_Cntl_port;
+  int               _TMC_Status_port;
+  int               _Write_FIFO_port;
+  int               _Write_SCSI_Data_port;
+
+  int               _FIFO_Size; /* = 0x2000;  8k FIFO for
+                                  pre-tmc18c30 chips */
+  /* simple stats */
+  int               _Bytes_Read;
+  int               _Bytes_Written;
+  int               _INTR_Processed;
+};
+
+#define FD_MAX_HOSTS 3         /* enough? */
+
+#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
+#define bios_base             (HOSTDATA(shpnt)->_bios_base)
+#define bios_major            (HOSTDATA(shpnt)->_bios_major)
+#define bios_minor            (HOSTDATA(shpnt)->_bios_minor)
+#define in_command            (HOSTDATA(shpnt)->_in_command)
+#define current_SC            (HOSTDATA(shpnt)->_current_SC)
+#define chip                  (HOSTDATA(shpnt)->_chip)
+#define adapter_mask          (HOSTDATA(shpnt)->_adapter_mask)
+#define FIFO_COUNT            (HOSTDATA(shpnt)->_fifo_count)
+#define adapter_name          (HOSTDATA(shpnt)->_adapter_name)
+#if DEBUG_RACE
+#define in_interrupt_flag     (HOSTDATA(shpnt)->_in_interrupt_flag)
+#endif                      
+#define SCSI_Mode_Cntl_port   (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
+#define FIFO_Data_Count_port  (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
+#define Interrupt_Cntl_port   (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
+#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
+#define Interrupt_Cond_port   (HOSTDATA(shpnt)->_Interrupt_Cond_port)
+#define Read_FIFO_port        (HOSTDATA(shpnt)->_Read_FIFO_port)
+#define Read_SCSI_Data_port   (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
+#define SCSI_Cntl_port        (HOSTDATA(shpnt)->_SCSI_Cntl_port)
+#define SCSI_Data_NoACK_port  (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
+#define SCSI_Status_port      (HOSTDATA(shpnt)->_SCSI_Status_port)
+#define TMC_Cntl_port         (HOSTDATA(shpnt)->_TMC_Cntl_port)
+#define TMC_Status_port       (HOSTDATA(shpnt)->_TMC_Status_port)
+#define Write_FIFO_port       (HOSTDATA(shpnt)->_Write_FIFO_port)
+#define Write_SCSI_Data_port  (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
+#define FIFO_Size             (HOSTDATA(shpnt)->_FIFO_Size)
+#define Bytes_Read            (HOSTDATA(shpnt)->_Bytes_Read)
+#define Bytes_Written         (HOSTDATA(shpnt)->_Bytes_Written)
+#define INTR_Processed        (HOSTDATA(shpnt)->_INTR_Processed)
+
+struct fd_mcs_adapters_struct {
+  char* name;
+  int id;
+  enum chip_type fd_chip;
+  int fifo_size;
+  int fifo_count;
+};
+
+#define REPLY_ID 0x5137
+
+static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
+  { "Future Domain SCSI Adapter MCS-700(18C50)",
+    0x60e9,
+    tmc18c50,
+    0x2000,
+    4 },
+  { "Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
+    0x6127,
+    tmc1800,
+    0x2000,
+    4 },
+  { "Reply Sound Blaster/SCSI Adapter",
+    REPLY_ID,
+    tmc18c30,
+    0x800,
+    2 },
+};
+
+#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct)
+
+static void fd_mcs_intr( int irq, void *dev_id, struct pt_regs * regs );
+
+static unsigned long addresses[] = {0xc8000, 0xca000, 0xce000, 0xde000};
+static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
+static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
+
+/* host information */
+static int found = 0;
+static struct Scsi_Host *hosts[FD_MAX_HOSTS+1] = { NULL };
+
+static int user_fifo_count = 0;
+static int user_fifo_size = 0;
+
+void fd_mcs_setup( char *str, int *ints )
+{
+  static int done_setup = 0;
+
+  if (done_setup++ || ints[0] < 1 || ints[0] > 2 ||
+      ints[1] < 1 || ints[1] > 16) {
+    printk( "fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n" );
+  }
+
+  user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
+  user_fifo_size  = ints[0] >= 2 ? ints[2] : 0;
+}
+
+static void print_banner( struct Scsi_Host *shpnt )
+{
+  printk( "scsi%d <fd_mcs>: ", shpnt->host_no);
+
+  if (bios_base) {
+    printk( "BIOS at 0x%lX", bios_base);
+  } else {
+    printk( "No BIOS");
+  }
+
+  printk( ", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n",
+          shpnt->this_id,
+          chip == tmc18c50 ? "TMC-18C50"
+             : (chip == tmc18c30 ? "TMC-18C30" :
+                (chip == tmc1800 ? "TMC-1800" : "Unknown")),
+          shpnt->irq,
+          shpnt->io_port );
+}
+
+
+static void do_pause( unsigned amount )        /* Pause for amount*10 milliseconds */
+{
+  do {
+    udelay(10*1000);
+  } while (--amount);
+}
+
+inline static void fd_mcs_make_bus_idle( struct Scsi_Host *shpnt )
+{
+  outb( 0, SCSI_Cntl_port );
+  outb( 0, SCSI_Mode_Cntl_port );
+  if (chip == tmc18c50 || chip == tmc18c30)
+    outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
+  else
+    outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
+}
+
+int fd_mcs_detect( Scsi_Host_Template *tpnt )
+{
+  int loop;
+  struct Scsi_Host *shpnt;
+
+  /* get id, port, bios, irq */
+  int slot;
+  u_char pos2, pos3, pos4;
+  int id, port, irq;
+  unsigned long bios;
+
+  /* if not MCA machine, return */
+  if (!MCA_bus)
+    return 0;
+
+  /* changeable? */
+  id = 7;
+
+  for( loop = 0; loop < FD_BRDS; loop++ ) {
+    slot = 0;
+    while ( MCA_NOTFOUND !=
+           (slot = mca_find_adapter(fd_mcs_adapters[loop].id,
+                                    slot)) ) {
+
+      /* if we get this far, an adapter has been detected and is
+        enabled */
+
+      printk("scsi  <fd_mcs>: %s at slot %d\n",
+            fd_mcs_adapters[loop].name, slot + 1 );
+
+      pos2 = mca_read_stored_pos( slot, 2 );
+      pos3 = mca_read_stored_pos( slot, 3 );
+      pos4 = mca_read_stored_pos( slot, 4);
+
+      /* ready for next probe */
+      slot++;
+
+      if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
+       static int reply_irq[] = {10, 11, 14, 15};
+
+       bios = 0;               /* no bios */
+
+       if (pos2 & 0x2)
+         port = ports[pos4 & 0x3];
+       else
+         continue;
+
+       /* can't really disable it, same as irq=10 */
+       irq = reply_irq[((pos4 >> 2) & 0x1) + 2*((pos4 >> 4) & 0x1)];
+      } else {
+       bios = addresses[pos2 >> 6];
+       port = ports[(pos2 >> 4) & 0x03];
+       irq = ints[(pos2 >> 1) & 0x07];
+      }
+
+      if (irq) {
+       /* claim the slot */
+       mca_set_adapter_name( slot-1, fd_mcs_adapters[loop].name );
+
+       /* check irq/region */
+       if (check_region(port, 0x10) ||
+           request_irq(irq, fd_mcs_intr,
+                       SA_SHIRQ, "fd_mcs", hosts)) {
+         printk( "fd_mcs: check_region() || request_irq() failed, Skip it\n");
+
+         continue;
+       }
+
+       /* register */
+       if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
+         printk( "fd_mcs: scsi_register() failed\n");
+         continue;
+       }
+
+       /* request I/O region */
+       request_region( port, 0x10, "fd_mcs" );
+
+       /* save name */
+       strcpy(adapter_name, fd_mcs_adapters[loop].name);
+
+       /* chip/fifo */
+       chip = fd_mcs_adapters[loop].fd_chip;
+       /* use boot time value if available */
+       FIFO_COUNT =
+         user_fifo_count?user_fifo_count:fd_mcs_adapters[loop].fifo_count;
+       FIFO_Size =
+         user_fifo_size?user_fifo_size:fd_mcs_adapters[loop].fifo_size;
+
+#ifdef NOT_USED
+       /* *************************************************** */
+       /* Try to toggle 32-bit mode.  This only
+          works on an 18c30 chip.  (User reports
+          say this works, so we should switch to
+          it in the near future.) */
+       outb( 0x80, port + IO_Control );
+       if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
+         outb( 0x00, port + IO_Control );
+         if ((inb( port + Configuration2 ) & 0x80) == 0x00) {
+           chip = tmc18c30;
+           FIFO_Size = 0x800;  /* 2k FIFO */
+
+           printk("FIRST: chip=%s, fifo_size=0x%x\n",
+                  (chip == tmc18c30)?"tmc18c30":"tmc18c50", FIFO_Size);
+         }
+       }
+
+       /* That should have worked, but appears to
+          have problems.  Let's assume it is an
+          18c30 if the RAM is disabled. */
+
+       if (inb( port + Configuration2 ) & 0x02) {
+         chip      = tmc18c30;
+         FIFO_Size = 0x800;    /* 2k FIFO */
+
+         printk("SECOND: chip=%s, fifo_size=0x%x\n",
+                (chip == tmc18c30)?"tmc18c30":"tmc18c50", FIFO_Size);
+       }
+       /* *************************************************** */           
+#endif
+
+#if 0
+       /* IBM/ANSI scsi scan ordering */
+       /* Stick this back in when the scsi.c changes are there */
+       shpnt->reverse_scan = 1;
+#endif
+       
+
+       /* saving info */
+       hosts[found++] = shpnt;
+
+       shpnt->this_id = id;
+       shpnt->irq = irq;
+       shpnt->io_port = port;
+       shpnt->n_io_port = 0x10;
+
+       /* save */
+       bios_base    = bios;
+       adapter_mask = (1 << id);
+
+       /* save more */
+       SCSI_Mode_Cntl_port   = port + SCSI_Mode_Cntl;
+       FIFO_Data_Count_port  = port + FIFO_Data_Count;
+       Interrupt_Cntl_port   = port + Interrupt_Cntl;
+       Interrupt_Status_port = port + Interrupt_Status;
+       Interrupt_Cond_port   = port + Interrupt_Cond;
+       Read_FIFO_port        = port + Read_FIFO;
+       Read_SCSI_Data_port   = port + Read_SCSI_Data;
+       SCSI_Cntl_port        = port + SCSI_Cntl;
+       SCSI_Data_NoACK_port  = port + SCSI_Data_NoACK;
+       SCSI_Status_port      = port + SCSI_Status;
+       TMC_Cntl_port         = port + TMC_Cntl;
+       TMC_Status_port       = port + TMC_Status;
+       Write_FIFO_port       = port + Write_FIFO;
+       Write_SCSI_Data_port  = port + Write_SCSI_Data;
+
+       Bytes_Read     = 0;
+       Bytes_Written  = 0;
+       INTR_Processed = 0;
+
+       /* say something */
+       print_banner( shpnt );
+
+       /* reset */
+       outb( 1, SCSI_Cntl_port );
+       do_pause( 2 );
+       outb( 0, SCSI_Cntl_port );
+       do_pause( 115 );
+       outb( 0, SCSI_Mode_Cntl_port );
+       outb( PARITY_MASK, TMC_Cntl_port );
+       /* done reset */
+
+#if DO_DETECT
+       /* scan devices attached */
+       {
+         const int     buflen = 255;
+         int           i, j, retcode;
+         Scsi_Cmnd     SCinit;
+         unsigned char do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
+         unsigned char do_request_sense[] = { REQUEST_SENSE, 
+                                              0, 0, 0, buflen, 0 };
+         unsigned char do_read_capacity[] = { READ_CAPACITY,
+                                              0, 0, 0, 0, 0, 0, 0, 0, 0 };
+         unsigned char buf[buflen];
+
+         SCinit.request_buffer  = SCinit.buffer = buf;
+         SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1;
+         SCinit.use_sg          = 0;
+         SCinit.lun             = 0;
+         SCinit.host            = shpnt;
+
+         printk( "fd_mcs: detection routine scanning for devices:\n" );
+         for (i = 0; i < 8; i++) {
+           if (i == shpnt->this_id)    /* Skip host adapter */
+             continue;
+           SCinit.target = i;
+           memcpy(SCinit.cmnd, do_request_sense,
+                  sizeof(do_request_sense));
+           retcode = fd_mcs_command(&SCinit);
+           if (!retcode) {
+             memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
+             retcode = fd_mcs_command(&SCinit);
+             if (!retcode) {
+               printk( "     SCSI ID %d: ", i );
+               for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
+                 printk( "%c", buf[j] >= 20 ? buf[j] : ' ' );
+               memcpy(SCinit.cmnd, do_read_capacity,
+                      sizeof(do_read_capacity));
+               retcode = fd_mcs_command(&SCinit);
+               if (!retcode) {
+                 unsigned long blocks, size, capacity;
+              
+                 blocks = (buf[0] << 24) | (buf[1] << 16)
+                   | (buf[2] << 8) | buf[3];
+                 size = (buf[4] << 24) | (buf[5] << 16) | 
+                   (buf[6] << 8) | buf[7];
+                 capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L;
+              
+                 printk( "%lu MB (%lu byte blocks)\n",
+                         ((capacity + 5L) / 10L), size );
+               }
+             }
+           }
+         }
+       }
+#endif
+      }
+    }
+
+    if (found == FD_MAX_HOSTS) {
+      printk( "fd_mcs: detecting reached max=%d host adapters.\n",
+             FD_MAX_HOSTS);
+      break;
+    }
+  }
+
+  return found;
+}
+
+const char *fd_mcs_info(struct Scsi_Host *shpnt)
+{
+  return adapter_name;
+}
+
+static int TOTAL_INTR = 0;
+
+/*
+ * inout : decides on the direction of the dataflow and the meaning of the 
+ *         variables
+ * buffer: If inout==FALSE data is being written to it else read from it
+ * *start: If inout==FALSE start of the valid data in the buffer
+ * offset: If inout==FALSE offset from the beginning of the imaginary file 
+ *         from which we start writing into the buffer
+ * length: If inout==FALSE max number of bytes to be written into the buffer 
+ *         else number of bytes in the buffer
+ */
+int fd_mcs_proc_info( char *buffer, char **start, off_t offset,
+                     int length, int hostno, int inout )
+{
+  struct Scsi_Host *shpnt;
+  int    len = 0;
+  int    i;
+
+  if (inout)
+    return(-ENOSYS);
+
+  *start = buffer + offset;
+
+  for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
+  shpnt = hosts[i];
+
+  if (!shpnt) {
+    return(-ENOENT);
+  } else {
+    len += sprintf(buffer+len, "Future Domain MCS-600/700 Driver %s\n",
+                  DRIVER_VERSION);
+
+    len += sprintf(buffer+len, "HOST #%d: %s\n",
+                  hostno, adapter_name);
+
+    len += sprintf(buffer+len, "FIFO Size=0x%x, FIFO Count=%d\n",
+                  FIFO_Size, FIFO_COUNT);
+
+    len += sprintf(buffer+len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n",
+                  TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
+  }
+
+  if ((len -= offset) <= 0)
+    return 0;
+  if (len > length) 
+    len = length;
+  return len;
+}
+   
+static int fd_mcs_select(struct Scsi_Host *shpnt, int target )
+{
+  int           status;
+  unsigned long timeout;
+
+  outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
+  outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
+
+  /* Stop arbitration and enable parity */
+  outb( PARITY_MASK, TMC_Cntl_port ); 
+
+  timeout = 350;               /* 350mS -- because of timeouts
+                                  (was 250mS) */
+
+  do {
+    status = inb( SCSI_Status_port ); /* Read adapter status */
+    if (status & 1) {                  /* Busy asserted */
+      /* Enable SCSI Bus (on error, should make bus idle with 0) */
+      outb( 0x80, SCSI_Cntl_port );
+      return 0;
+    }
+    udelay(1000);              /* wait one msec */
+  } while (--timeout);
+
+  /* Make bus idle */
+  fd_mcs_make_bus_idle(shpnt);
+#if EVERY_ACCESS
+  if (!target) printk( "Selection failed\n" );
+#endif
+#if ERRORS_ONLY
+  if (!target) {
+    static int flag = 0;
+
+    if (!flag) /* Skip first failure for all chips. */
+      ++flag;
+    else
+      printk( "fd_mcs: Selection failed\n" );
+  }
+#endif
+  return 1;
+}
+
+static void my_done( struct Scsi_Host *shpnt, int error )
+{
+  if (in_command) {
+    in_command = 0;
+    outb( 0x00, Interrupt_Cntl_port );
+    fd_mcs_make_bus_idle(shpnt);
+    current_SC->result = error;
+    current_SC->scsi_done( current_SC );
+  } else {
+    panic( "fd_mcs: my_done() called outside of command\n" );
+  }
+#if DEBUG_RACE
+  in_interrupt_flag = 0;
+#endif
+}
+
+/* only my_done needs to be protected  */
+static void fd_mcs_intr( int irq, void *dev_id, struct pt_regs * regs )
+{
+  unsigned long flags;
+  int      status;
+  int      done = 0;
+  unsigned data_count, tmp_count;
+
+  int i = 0;
+  struct Scsi_Host *shpnt;
+
+  TOTAL_INTR++;
+
+  /* search for one adapter-response on shared interrupt */
+  while ((shpnt = hosts[i++])) {
+    if ((inb(TMC_Status_port)) & 1)
+      break;
+  }
+  /* return if some other device on this IRQ caused the interrupt */
+  if (!shpnt) {
+    return;
+  }
+
+  INTR_Processed++;
+
+  outb( 0x00, Interrupt_Cntl_port );
+
+  /* Abort calls my_done, so we do nothing here. */
+  if (current_SC->SCp.phase & aborted) {
+#if DEBUG_ABORT
+    printk( "Interrupt after abort, ignoring\n" );
+#endif
+    /* return; */
+  }
+
+#if DEBUG_RACE
+  ++in_interrupt_flag;
+#endif
+
+  if (current_SC->SCp.phase & in_arbitration) {
+    status = inb( TMC_Status_port );        /* Read adapter status */
+    if (!(status & 0x02)) {
+#if EVERY_ACCESS
+      printk( " AFAIL " );
+#endif
+      spin_lock_irqsave(&io_request_lock, flags);
+      my_done( shpnt, DID_BUS_BUSY << 16 );
+      spin_unlock_irqrestore(&io_request_lock, flags);
+      return;
+    }
+    current_SC->SCp.phase = in_selection;
+      
+    outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
+
+    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
+    outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
+      
+    /* Stop arbitration and enable parity */
+    outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
+#if DEBUG_RACE
+    in_interrupt_flag = 0;
+#endif
+    return;
+  } else if (current_SC->SCp.phase & in_selection) {
+    status = inb( SCSI_Status_port );
+    if (!(status & 0x01)) {
+      /* Try again, for slow devices */
+      if (fd_mcs_select(shpnt, current_SC->target )) {
+#if EVERY_ACCESS
+       printk( " SFAIL " );
+#endif
+       spin_lock_irqsave(&io_request_lock, flags);
+       my_done( shpnt, DID_NO_CONNECT << 16 );
+       spin_unlock_irqrestore(&io_request_lock, flags);
+       return;
+      } else {
+#if EVERY_ACCESS
+       printk( " AltSel " );
+#endif
+       /* Stop arbitration and enable parity */
+       outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
+      }
+    }
+    current_SC->SCp.phase = in_other;
+    outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
+    outb( 0x80, SCSI_Cntl_port );
+#if DEBUG_RACE
+    in_interrupt_flag = 0;
+#endif
+    return;
+  }
+   
+  /* current_SC->SCp.phase == in_other: this is the body of the routine */
+   
+  status = inb( SCSI_Status_port );
+   
+  if (status & 0x10) { /* REQ */
+      
+    switch (status & 0x0e) {
+       
+    case 0x08:         /* COMMAND OUT */
+      outb( current_SC->cmnd[current_SC->SCp.sent_command++],
+           Write_SCSI_Data_port );
+#if EVERY_ACCESS
+      printk( "CMD = %x,",
+             current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
+#endif
+      break;
+    case 0x00:         /* DATA OUT -- tmc18c50/tmc18c30 only */
+      if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
+       current_SC->SCp.have_data_in = -1;
+       outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
+      }
+      break;
+    case 0x04:         /* DATA IN -- tmc18c50/tmc18c30 only */
+      if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
+       current_SC->SCp.have_data_in = 1;
+       outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
+      }
+      break;
+    case 0x0c:         /* STATUS IN */
+      current_SC->SCp.Status = inb( Read_SCSI_Data_port );
+#if EVERY_ACCESS
+      printk( "Status = %x, ", current_SC->SCp.Status );
+#endif
+#if ERRORS_ONLY
+      if (current_SC->SCp.Status
+         && current_SC->SCp.Status != 2
+         && current_SC->SCp.Status != 8) {
+       printk( "ERROR fd_mcs: target = %d, command = %x, status = %x\n",
+               current_SC->target,
+               current_SC->cmnd[0],
+               current_SC->SCp.Status );
+      }
+#endif
+      break;
+    case 0x0a:         /* MESSAGE OUT */
+      outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
+      break;
+    case 0x0e:         /* MESSAGE IN */
+      current_SC->SCp.Message = inb( Read_SCSI_Data_port );
+#if EVERY_ACCESS
+      printk( "Message = %x, ", current_SC->SCp.Message );
+#endif
+      if (!current_SC->SCp.Message) ++done;
+#if DEBUG_MESSAGES || EVERY_ACCESS
+      if (current_SC->SCp.Message) {
+       printk( "fd_mcs: message = %x\n", current_SC->SCp.Message );
+      }
+#endif
+      break;
+    }
+  }
+
+  if (chip == tmc1800
+      && !current_SC->SCp.have_data_in
+      && (current_SC->SCp.sent_command
+         >= current_SC->cmd_len)) {
+    /* We have to get the FIFO direction
+       correct, so I've made a table based
+       on the SCSI Standard of which commands
+       appear to require a DATA OUT phase.
+       */
+    /*
+      p. 94: Command for all device types
+      CHANGE DEFINITION            40 DATA OUT
+      COMPARE                      39 DATA OUT
+      COPY                         18 DATA OUT
+      COPY AND VERIFY              3a DATA OUT
+      INQUIRY                      12 
+      LOG SELECT                   4c DATA OUT
+      LOG SENSE                    4d
+      MODE SELECT (6)              15 DATA OUT
+      MODE SELECT (10)             55 DATA OUT
+      MODE SENSE (6)               1a
+      MODE SENSE (10)              5a
+      READ BUFFER                  3c
+      RECEIVE DIAGNOSTIC RESULTS   1c
+      REQUEST SENSE                03
+      SEND DIAGNOSTIC              1d DATA OUT
+      TEST UNIT READY              00
+      WRITE BUFFER                 3b DATA OUT
+
+      p.178: Commands for direct-access devices (not listed on p. 94)
+      FORMAT UNIT                  04 DATA OUT
+      LOCK-UNLOCK CACHE            36
+      PRE-FETCH                    34
+      PREVENT-ALLOW MEDIUM REMOVAL 1e
+      READ (6)/RECEIVE             08
+      READ (10)                    3c
+      READ CAPACITY                25
+      READ DEFECT DATA (10)        37
+      READ LONG                    3e
+      REASSIGN BLOCKS              07 DATA OUT
+      RELEASE                      17
+      RESERVE                      16 DATA OUT
+      REZERO UNIT/REWIND           01
+      SEARCH DATA EQUAL (10)       31 DATA OUT
+      SEARCH DATA HIGH (10)        30 DATA OUT
+      SEARCH DATA LOW (10)         32 DATA OUT
+      SEEK (6)                     0b
+      SEEK (10)                    2b
+      SET LIMITS (10)              33
+      START STOP UNIT              1b
+      SYNCHRONIZE CACHE            35
+      VERIFY (10)                  2f
+      WRITE (6)/PRINT/SEND         0a DATA OUT
+      WRITE (10)/SEND              2a DATA OUT
+      WRITE AND VERIFY (10)        2e DATA OUT
+      WRITE LONG                   3f DATA OUT
+      WRITE SAME                   41 DATA OUT ?
+
+      p. 261: Commands for sequential-access devices (not previously listed)
+      ERASE                        19
+      LOAD UNLOAD                  1b
+      LOCATE                       2b
+      READ BLOCK LIMITS            05
+      READ POSITION                34
+      READ REVERSE                 0f
+      RECOVER BUFFERED DATA        14
+      SPACE                        11
+      WRITE FILEMARKS              10 ?
+
+      p. 298: Commands for printer devices (not previously listed)
+      ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
+      SLEW AND PRINT               0b DATA OUT  -- same as seek
+      STOP PRINT                   1b
+      SYNCHRONIZE BUFFER           10
+
+      p. 315: Commands for processor devices (not previously listed)
+       
+      p. 321: Commands for write-once devices (not previously listed)
+      MEDIUM SCAN                  38
+      READ (12)                    a8
+      SEARCH DATA EQUAL (12)       b1 DATA OUT
+      SEARCH DATA HIGH (12)        b0 DATA OUT
+      SEARCH DATA LOW (12)         b2 DATA OUT
+      SET LIMITS (12)              b3
+      VERIFY (12)                  af
+      WRITE (12)                   aa DATA OUT
+      WRITE AND VERIFY (12)        ae DATA OUT
+
+      p. 332: Commands for CD-ROM devices (not previously listed)
+      PAUSE/RESUME                 4b
+      PLAY AUDIO (10)              45
+      PLAY AUDIO (12)              a5
+      PLAY AUDIO MSF               47
+      PLAY TRACK RELATIVE (10)     49
+      PLAY TRACK RELATIVE (12)     a9
+      READ HEADER                  44
+      READ SUB-CHANNEL             42
+      READ TOC                     43
+
+      p. 370: Commands for scanner devices (not previously listed)
+      GET DATA BUFFER STATUS       34
+      GET WINDOW                   25
+      OBJECT POSITION              31
+      SCAN                         1b
+      SET WINDOW                   24 DATA OUT
+
+      p. 391: Commands for optical memory devices (not listed)
+      ERASE (10)                   2c
+      ERASE (12)                   ac
+      MEDIUM SCAN                  38 DATA OUT
+      READ DEFECT DATA (12)        b7
+      READ GENERATION              29
+      READ UPDATED BLOCK           2d
+      UPDATE BLOCK                 3d DATA OUT
+
+      p. 419: Commands for medium changer devices (not listed)
+      EXCHANGE MEDIUM              46
+      INITIALIZE ELEMENT STATUS    07
+      MOVE MEDIUM                  a5
+      POSITION TO ELEMENT          2b
+      READ ELEMENT STATUS          b8
+      REQUEST VOL. ELEMENT ADDRESS b5
+      SEND VOLUME TAG              b6 DATA OUT
+
+      p. 454: Commands for communications devices (not listed previously)
+      GET MESSAGE (6)              08
+      GET MESSAGE (10)             28
+      GET MESSAGE (12)             a8
+      */
+       
+    switch (current_SC->cmnd[0]) {
+    case CHANGE_DEFINITION: case COMPARE:         case COPY:
+    case COPY_VERIFY:       case LOG_SELECT:      case MODE_SELECT:
+    case MODE_SELECT_10:    case SEND_DIAGNOSTIC: case WRITE_BUFFER:
+
+    case FORMAT_UNIT:       case REASSIGN_BLOCKS: case RESERVE:
+    case SEARCH_EQUAL:      case SEARCH_HIGH:     case SEARCH_LOW:
+    case WRITE_6:           case WRITE_10:        case WRITE_VERIFY:
+    case 0x3f:              case 0x41:
+
+    case 0xb1:              case 0xb0:            case 0xb2:
+    case 0xaa:              case 0xae:
+
+    case 0x24:
+
+    case 0x38:              case 0x3d:
+
+    case 0xb6:
+        
+    case 0xea:         /* alternate number for WRITE LONG */
+        
+      current_SC->SCp.have_data_in = -1;
+      outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
+      break;
+
+    case 0x00:
+    default:
+        
+      current_SC->SCp.have_data_in = 1;
+      outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
+      break;
+    }
+  }
+
+  if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
+    while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
+#if EVERY_ACCESS
+      printk( "DC=%d, ", data_count ) ;
+#endif
+      if (data_count > current_SC->SCp.this_residual)
+       data_count = current_SC->SCp.this_residual;
+      if (data_count > 0) {
+#if EVERY_ACCESS
+       printk( "%d OUT, ", data_count );
+#endif
+       if (data_count == 1) {
+         Bytes_Written++;
+
+         outb( *current_SC->SCp.ptr++, Write_FIFO_port );
+         --current_SC->SCp.this_residual;
+       } else {
+         data_count >>= 1;
+         tmp_count = data_count << 1;
+         outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
+         current_SC->SCp.ptr += tmp_count;
+         Bytes_Written += tmp_count;
+         current_SC->SCp.this_residual -= tmp_count;
+       }
+      }
+      if (!current_SC->SCp.this_residual) {
+       if (current_SC->SCp.buffers_residual) {
+         --current_SC->SCp.buffers_residual;
+         ++current_SC->SCp.buffer;
+         current_SC->SCp.ptr = current_SC->SCp.buffer->address;
+         current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+       } else
+         break;
+      }
+    }
+  } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
+    while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
+#if EVERY_ACCESS
+      printk( "DC=%d, ", data_count );
+#endif
+      if (data_count > current_SC->SCp.this_residual)
+       data_count = current_SC->SCp.this_residual;
+      if (data_count) {
+#if EVERY_ACCESS
+       printk( "%d IN, ", data_count );
+#endif
+       if (data_count == 1) {
+         Bytes_Read++;
+         *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
+         --current_SC->SCp.this_residual;
+       } else {
+         data_count >>= 1; /* Number of words */
+         tmp_count = data_count << 1;
+         insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
+         current_SC->SCp.ptr += tmp_count;
+         Bytes_Read += tmp_count;
+         current_SC->SCp.this_residual -= tmp_count;
+       }
+      }
+      if (!current_SC->SCp.this_residual
+         && current_SC->SCp.buffers_residual) {
+       --current_SC->SCp.buffers_residual;
+       ++current_SC->SCp.buffer;
+       current_SC->SCp.ptr = current_SC->SCp.buffer->address;
+       current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+      }
+    }
+  }
+   
+  if (done) {
+#if EVERY_ACCESS
+    printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
+#endif
+
+#if ERRORS_ONLY
+    if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
+      if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) {
+       unsigned char key;
+       unsigned char code;
+       unsigned char qualifier;
+
+       key = (unsigned char)(*((char *)current_SC->request_buffer + 2))
+         & 0x0f;
+       code = (unsigned char)(*((char *)current_SC->request_buffer + 12));
+       qualifier = (unsigned char)(*((char *)current_SC->request_buffer
+                                     + 13));
+
+       if (key != UNIT_ATTENTION
+           && !(key == NOT_READY
+                && code == 0x04
+                && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
+           && !(key == ILLEGAL_REQUEST && (code == 0x25
+                                           || code == 0x24
+                                           || !code)))
+                 
+         printk( "fd_mcs: REQUEST SENSE "
+                 "Key = %x, Code = %x, Qualifier = %x\n",
+                 key, code, qualifier );
+      }
+    }
+#endif
+#if EVERY_ACCESS
+    printk( "BEFORE MY_DONE. . ." );
+#endif
+    spin_lock_irqsave(&io_request_lock, flags);
+    my_done( shpnt,
+            (current_SC->SCp.Status & 0xff)
+            | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
+    spin_unlock_irqrestore(&io_request_lock, flags);
+#if EVERY_ACCESS
+    printk( "RETURNING.\n" );
+#endif
+      
+  } else {
+    if (current_SC->SCp.phase & disconnect) {
+      outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
+      outb( 0x00, SCSI_Cntl_port );
+    } else {
+      outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
+    }
+  }
+#if DEBUG_RACE
+  in_interrupt_flag = 0;
+#endif
+  return;
+}
+
+int fd_mcs_release(struct Scsi_Host *shpnt)
+{
+  int i, this_host, irq_usage;
+
+  release_region(shpnt->io_port, shpnt->n_io_port);
+
+  this_host = -1;
+  irq_usage = 0;
+  for (i = 0; i < found; i++) {
+    if (shpnt == hosts[i])
+      this_host = i;
+    if (shpnt->irq == hosts[i]->irq)
+      irq_usage++;
+  }
+
+  /* only for the last one */
+  if (1 == irq_usage)
+    free_irq(shpnt->irq, hosts);
+
+  found--;
+
+  for (i = this_host; i < found; i++)
+    hosts[i] = hosts[i+1];
+
+  hosts[found] = NULL;
+
+  return 0;
+}
+
+int fd_mcs_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+{
+  struct Scsi_Host *shpnt = SCpnt->host;
+
+  if (in_command) {
+    panic( "fd_mcs: fd_mcs_queue() NOT REENTRANT!\n" );
+  }
+#if EVERY_ACCESS
+  printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
+         SCpnt->target,
+         *(unsigned char *)SCpnt->cmnd,
+         SCpnt->use_sg,
+         SCpnt->request_bufflen );
+#endif
+
+  fd_mcs_make_bus_idle(shpnt);
+
+  SCpnt->scsi_done = done;     /* Save this for the done function */
+  current_SC       = SCpnt;
+
+  /* Initialize static data */
+
+  if (current_SC->use_sg) {
+    current_SC->SCp.buffer =
+      (struct scatterlist *)current_SC->request_buffer;
+    current_SC->SCp.ptr              = current_SC->SCp.buffer->address;
+    current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
+    current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
+  } else {
+    current_SC->SCp.ptr              = (char *)current_SC->request_buffer;
+    current_SC->SCp.this_residual    = current_SC->request_bufflen;
+    current_SC->SCp.buffer           = NULL;
+    current_SC->SCp.buffers_residual = 0;
+  }
+        
+   
+  current_SC->SCp.Status              = 0;
+  current_SC->SCp.Message             = 0;
+  current_SC->SCp.have_data_in        = 0;
+  current_SC->SCp.sent_command        = 0;
+  current_SC->SCp.phase               = in_arbitration;
+
+  /* Start arbitration */
+  outb( 0x00, Interrupt_Cntl_port );
+  outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
+  outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
+  in_command = 1;
+  outb( 0x20, Interrupt_Cntl_port );
+  outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
+
+  return 0;
+}
+
+static void internal_done( Scsi_Cmnd *SCpnt )
+{
+  /* flag it done */
+  SCpnt->host_scribble = (unsigned char *)1;
+}
+
+int fd_mcs_command( Scsi_Cmnd *SCpnt )
+{
+  fd_mcs_queue( SCpnt, internal_done );
+  /* host_scribble is used for status here */
+  SCpnt->host_scribble = NULL;
+  while (!SCpnt->host_scribble)
+    barrier();
+  return SCpnt->result;
+}
+
+#if DEBUG_ABORT || DEBUG_RESET
+static void fd_mcs_print_info( Scsi_Cmnd *SCpnt )
+{
+  unsigned int imr;
+  unsigned int irr;
+  unsigned int isr;
+  struct Scsi_Host *shpnt = SCpnt->host;
+
+  if (!SCpnt || !SCpnt->host) {
+    printk( "fd_mcs: cannot provide detailed information\n" );
+  }
+   
+  printk( "%s\n", fd_mcs_info( SCpnt->host ) );
+  print_banner( SCpnt->host );
+  switch (SCpnt->SCp.phase) {
+  case in_arbitration: printk( "arbitration " ); break;
+  case in_selection:   printk( "selection " );   break;
+  case in_other:       printk( "other " );       break;
+  default:             printk( "unknown " );     break;
+  }
+
+  printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
+         SCpnt->SCp.phase,
+         SCpnt->target,
+         *(unsigned char *)SCpnt->cmnd,
+         SCpnt->use_sg,
+         SCpnt->request_bufflen );
+  printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
+         SCpnt->SCp.sent_command,
+         SCpnt->SCp.have_data_in,
+         SCpnt->timeout );
+#if DEBUG_RACE
+  printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
+#endif
+
+  imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
+  outb( 0x0a, 0xa0 );
+  irr = inb( 0xa0 ) << 8;
+  outb( 0x0a, 0x20 );
+  irr += inb( 0x20 );
+  outb( 0x0b, 0xa0 );
+  isr = inb( 0xa0 ) << 8;
+  outb( 0x0b, 0x20 );
+  isr += inb( 0x20 );
+
+  /* Print out interesting information */
+  printk( "IMR = 0x%04x", imr );
+  if (imr & (1 << shpnt->irq))
+    printk( " (masked)" );
+  printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
+
+  printk( "SCSI Status      = 0x%02x\n", inb( SCSI_Status_port ) );
+  printk( "TMC Status       = 0x%02x", inb( TMC_Status_port ) );
+  if (inb( TMC_Status_port ) & 1)
+    printk( " (interrupt)" );
+  printk( "\n" );
+  printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
+  if (inb( Interrupt_Status_port ) & 0x08)
+    printk( " (enabled)" );
+  printk( "\n" );
+  if (chip == tmc18c50 || chip == tmc18c30) {
+    printk( "FIFO Status      = 0x%02x\n", inb( shpnt->io_port + FIFO_Status ) );
+    printk( "Int. Condition   = 0x%02x\n",
+           inb( shpnt->io_port + Interrupt_Cond ) );
+  }
+  printk( "Configuration 1  = 0x%02x\n", inb( shpnt->io_port + Configuration1 ) );
+  if (chip == tmc18c50 || chip == tmc18c30)
+    printk( "Configuration 2  = 0x%02x\n",
+           inb( shpnt->io_port + Configuration2 ) );
+}
+#endif
+
+int fd_mcs_abort( Scsi_Cmnd *SCpnt)
+{
+  struct Scsi_Host *shpnt = SCpnt->host;
+
+  unsigned long flags;
+#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
+  printk( "fd_mcs: abort " );
+#endif
+
+  save_flags( flags );
+  cli();
+  if (!in_command) {
+#if EVERY_ACCESS || ERRORS_ONLY
+    printk( " (not in command)\n" );
+#endif
+    restore_flags( flags );
+    return SCSI_ABORT_NOT_RUNNING;
+  } else printk( "\n" );
+
+#if DEBUG_ABORT
+  fd_mcs_print_info( SCpnt );
+#endif
+
+  fd_mcs_make_bus_idle(shpnt);
+
+  current_SC->SCp.phase |= aborted;
+
+  current_SC->result = DID_ABORT << 16;
+
+  restore_flags( flags );
+   
+  /* Aborts are not done well. . . */
+  spin_lock_irqsave(&io_request_lock, flags);
+  my_done( shpnt, DID_ABORT << 16 );
+  spin_unlock_irqrestore(&io_request_lock, flags);
+
+  return SCSI_ABORT_SUCCESS;
+}
+
+int fd_mcs_reset( Scsi_Cmnd *SCpnt, unsigned int reset_flags )
+{
+  struct Scsi_Host *shpnt = SCpnt->host;
+
+#if DEBUG_RESET
+  static int called_once = 0;
+#endif
+
+#if ERRORS_ONLY
+  if (SCpnt) printk( "fd_mcs: SCSI Bus Reset\n" );
+#endif
+
+#if DEBUG_RESET
+  if (called_once) fd_mcs_print_info( current_SC );
+  called_once = 1;
+#endif
+   
+  outb( 1, SCSI_Cntl_port );
+  do_pause( 2 );
+  outb( 0, SCSI_Cntl_port );
+  do_pause( 115 );
+  outb( 0, SCSI_Mode_Cntl_port );
+  outb( PARITY_MASK, TMC_Cntl_port );
+
+  /* Unless this is the very first call (i.e., SCPnt == NULL), everything
+     is probably hosed at this point.  We will, however, try to keep
+     things going by informing the high-level code that we need help. */
+
+  return SCSI_RESET_WAKEUP;
+}
+
+#include "sd.h"
+#include <scsi/scsi_ioctl.h>
+
+int fd_mcs_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
+{
+  int              drive;
+  unsigned char    buf[512 + sizeof( int ) * 2];
+  int              size      = disk->capacity;
+  int              *sizes    = (int *)buf;
+  unsigned char    *data     = (unsigned char *)(sizes + 2);
+  unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
+  int              retcode;
+
+  /* BIOS >= 3.4 for MCA cards */
+  drive = MINOR(dev) / 16;
+
+  /* This algorithm was provided by Future Domain (much thanks!). */
+
+  sizes[0] = 0;                /* zero bytes out */
+  sizes[1] = 512;              /* one sector in */
+  memcpy( data, do_read, sizeof( do_read ) );
+  retcode = kernel_scsi_ioctl( disk->device,
+                              SCSI_IOCTL_SEND_COMMAND,
+                              (void *)buf );
+  if (!retcode                             /* SCSI command ok */
+      && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
+      && data[0x1c2]) {                            /* Partition type */
+
+    /* The partition table layout is as follows:
+
+        Start: 0x1b3h
+        Offset: 0 = partition status
+        1 = starting head
+        2 = starting sector and cylinder (word, encoded)
+        4 = partition type
+        5 = ending head
+        6 = ending sector and cylinder (word, encoded)
+        8 = starting absolute sector (double word)
+        c = number of sectors (double word)
+        Signature: 0x1fe = 0x55aa
+
+        So, this algorithm assumes:
+        1) the first partition table is in use,
+        2) the data in the first entry is correct, and
+        3) partitions never divide cylinders
+
+        Note that (1) may be FALSE for NetBSD (and other BSD flavors),
+        as well as for Linux.  Note also, that Linux doesn't pay any
+        attention to the fields that are used by this algorithm -- it
+        only uses the absolute sector data.  Recent versions of Linux's
+        fdisk(1) will fill this data in correctly, and forthcoming
+        versions will check for consistency.
+
+        Checking for a non-zero partition type is not part of the
+        Future Domain algorithm, but it seemed to be a reasonable thing
+        to do, especially in the Linux and BSD worlds. */
+
+    info_array[0] = data[0x1c3] + 1;       /* heads */
+    info_array[1] = data[0x1c4] & 0x3f;            /* sectors */
+  } else {
+
+    /* Note that this new method guarantees that there will always be
+        less than 1024 cylinders on a platter.  This is good for drives
+        up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
+
+    if ((unsigned int)size >= 0x7e0000U) {
+      info_array[0] = 0xff; /* heads   = 255 */
+      info_array[1] = 0x3f; /* sectors =  63 */
+    } else if ((unsigned int)size >= 0x200000U) {
+      info_array[0] = 0x80; /* heads   = 128 */
+      info_array[1] = 0x3f; /* sectors =  63 */
+    } else {
+      info_array[0] = 0x40; /* heads   =  64 */
+      info_array[1] = 0x20; /* sectors =  32 */
+    }
+  }
+  /* For both methods, compute the cylinders */
+  info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
+
+   
+  return 0;
+}
+
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = FD_MCS;
+
+#include "scsi_module.c"
+#endif
diff --git a/drivers/scsi/fd_mcs.h b/drivers/scsi/fd_mcs.h
new file mode 100644 (file)
index 0000000..e96cc21
--- /dev/null
@@ -0,0 +1,54 @@
+/* fd_mcs.h -- Header for Future Domain MCS 600/700 (or IBM OEM) driver
+ * 
+ * fd_mcs.h v0.2 03/11/1998 ZP Gu (zpg@castle.net)
+ *
+
+ * 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, or (at your option) any
+ * later version.
+
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+
+#ifndef _FD_MCS_H
+#define _FD_MCS_H
+
+extern int fd_mcs_detect( Scsi_Host_Template * );
+extern int fd_mcs_release( struct Scsi_Host * );
+extern int fd_mcs_command( Scsi_Cmnd * );
+extern int fd_mcs_abort( Scsi_Cmnd * );
+extern int fd_mcs_reset( Scsi_Cmnd *, unsigned int );
+extern int fd_mcs_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
+extern int fd_mcs_biosparam( Disk *, kdev_t, int * );
+extern int fd_mcs_proc_info( char *, char **, off_t, int, int, int );
+extern const char *fd_mcs_info(struct Scsi_Host *);
+
+extern struct proc_dir_entry proc_scsi_fd_mcs;
+
+#define FD_MCS {\
+                    proc_dir:       &proc_scsi_fd_mcs,          \
+                    proc_info:      fd_mcs_proc_info,           \
+                   detect:         fd_mcs_detect,              \
+                   release:        fd_mcs_release,             \
+                   info:           fd_mcs_info,                \
+                   command:        fd_mcs_command,             \
+                   queuecommand:   fd_mcs_queue,               \
+                   abort:          fd_mcs_abort,               \
+                   reset:          fd_mcs_reset,               \
+                   bios_param:     fd_mcs_biosparam,           \
+                   can_queue:      1,                          \
+                   this_id:        7,                          \
+                   sg_tablesize:   64,                         \
+                   cmd_per_lun:    1,                          \
+                   use_clustering: DISABLE_CLUSTERING }
+
+#endif /* _FD_MCS_H */
index 2ab1f5689dbbc8aac05b3221b0e990390f89746a..2088c0ede5d797f638659a7eeb037803f6036962 100644 (file)
 #include "u14-34f.h"
 #endif
 
+#ifdef CONFIG_SCSI_FD_MCS
+#include "fd_mcs.h"
+#endif
+
 #ifdef CONFIG_SCSI_FUTURE_DOMAIN
 #include "fdomain.h"
 #endif
index 6c0b6edd5cbb8a2147796764a576caa385732f55..9aa0d8fbc1caa2bd08cf14e14c6b8c40887b1d5f 100644 (file)
@@ -45,6 +45,7 @@ int scsicam_bios_param (Disk *disk, /* SCSI disk */
     struct buffer_head *bh;
     int ret_code;
     int size = disk->capacity;
+    unsigned long temp_cyl;
 
     if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024)))
        return -1;
@@ -67,6 +68,11 @@ int scsicam_bios_param (Disk *disk, /* SCSI disk */
     if (ret_code || ip[0] > 255 || ip[1] > 63) {
         ip[0] = 64;
         ip[1] = 32;
+        temp_cyl = size / (ip[0] * ip[1]);
+        if (temp_cyl > 65534) {
+             ip[0] = 255;
+             ip[1] = 63;
+        }
         ip[2] = size / (ip[0] * ip[1]);
     }
 
index 9740035b47cc4d23a839b20e49ca4fa13d7cea2d..670fbe87b69a67c8342260d0d94530250a40c95a 100644 (file)
@@ -66,6 +66,34 @@ modprobe -k adlib_card io=0x388
 
  recommend using /etc/modules.conf.
 
+Persistent DMA Buffers:
+
+The sound modules normally allocate DMA buffers during open() and
+deallocate them during close(). Linux can often have problems allocating
+DMA buffers for ISA cards on machines with more than 16MB RAM. This is
+because ISA DMA buffers must exist below the 16MB boundry and it is quite
+possible that we can't find a large enough free block in this region after
+the machine has been running for any amount of time. The way to avoid this
+problem is to allocate the DMA buffers during module load and deallocate
+them when the module is unloaded. For this to be effective we need to load
+the sound modules right after the kernel boots, either manually or by an
+init script, and keep them around until we shut down. This is a little
+wasteful of RAM, but it guarantees that sound always works.
+
+To make the sound driver use persistent DMA buffers we need to pass the
+sound.o module a "dmabuf=1" command-line argument. This is normally done
+in /etc/conf.modules (or the more proper /etc/modules.conf) like so:
+
+options sound          dmabuf=1
+
+If you have 16MB or less RAM or a PCI sound card, this is wasteful and
+unnecessary. It is possible that machine with 16MB or less RAM will find
+this option useful, but if your machine is so memory-starved that it
+cannot find a 64K block free, you will be wasting even more RAM by keeping
+the sound modules loaded and the DMA buffers allocated when they are not
+needed. The proper solution is to upgrade your RAM. But you do also have
+this improper solution as well. Use it wisely.
+
   I'm afraid I know nothing about anything but my setup, being more of a
 text-mode guy anyway. If you have options for other cards or other helpful
 hints, send them to me, Jim Bray, jb@as220.org, http://as220.org/jb.
index a9ccdfc2e84326dd251dc9e40af2c913357d0e64..e004a48cec7126ecf79fbdcf0959f09f28790360 100644 (file)
@@ -1814,7 +1814,7 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt
                        ad_write(devc, 16, tmp & ~0x40);        /* Disable timer */
 
                        if (devc->timer_ticks == 0)
-                               printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", devc->irq);
+                               printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", irq);
                        else
                        {
                                DDB(printk("Interrupt test OK\n"));
@@ -1935,7 +1935,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
                if (!share_dma)
                {
                        if (irq > 0)
-                               free_irq(devc->irq, NULL);
+                               free_irq(devc->irq, (void *)devc->dev_no);
 
                        sound_free_dma(audio_devs[dev]->dmap_out->dma);
 
@@ -1945,6 +1945,10 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
                mixer = audio_devs[devc->dev_no]->mixer_dev;
                if(mixer>=0)
                        sound_unload_mixerdev(mixer);
+
+               nr_ad1848_devs--;
+               for ( ; i < nr_ad1848_devs ; i++)
+                       adev_info[i] = adev_info[i+1];
        }
        else
                printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base);
index 0cf1858c23a6c105bc2f0373be3ef21e50d51be7..286eca0116b63774b33ee651fdecec3082863e70 100644 (file)
@@ -228,8 +228,8 @@ int audio_write(int dev, struct file *file, const char *buf, int count)
                if (l > buf_size)
                        l = buf_size;
 
-        returned = l;
-        used = l;
+               returned = l;
+               used = l;
                if (!audio_devs[dev]->d->copy_user)
                {
                        if ((dma_buf + l) >
@@ -246,13 +246,13 @@ int audio_write(int dev, struct file *file, const char *buf, int count)
                        if(copy_from_user(dma_buf, &(buf)[p], l))
                                return -EFAULT;
                } 
-               else audio_devs[dev]->d->copy_user ( dev,
-                                             dma_buf, 0,
-                                             buf, p,
-                                             c, buf_size,
-                                             &used, &returned,
-                                             l);
-        l = returned;
+               else audio_devs[dev]->d->copy_user (dev,
+                                               dma_buf, 0,
+                                               buf, p,
+                                               c, buf_size,
+                                               &used, &returned,
+                                               l);
+               l = returned;
 
                if (audio_devs[dev]->local_conversion & CNV_MU_LAW)
                {
index 6ffa1d19d85ee47420af63fd9ad9341ad1af0a53..7e5c4b76c71dfbae9c84d774436d0352b2348a7e 100644 (file)
@@ -516,6 +516,7 @@ void sound_unload_audiodev(int dev)
 {
        if (dev != -1)
        {
+               DMAbuf_deinit(dev);
                audio_devs[dev] = NULL;
                unregister_sound_dsp((dev<<4)+3);
        }
index 90860d33d41e49038fca0fe9b86e7e61f48e8dee..b440f3c095d3ca3276c2dabcc08b5eadf1dffb57 100644 (file)
@@ -188,12 +188,12 @@ struct audio_driver
        int (*prepare_for_output) (int dev, int bufsize, int nbufs);
        void (*halt_io) (int dev);
        int (*local_qlen)(int dev);
-    void (*copy_user)(int dev,
-                      char *localbuf, int localoffs,
-                      const char *userbuf, int useroffs,
-                      int max_in, int max_out,
-                      int *used, int *returned,
-                      int len);
+       void (*copy_user) (int dev,
+                       char *localbuf, int localoffs,
+                        const char *userbuf, int useroffs,
+                        int max_in, int max_out,
+                        int *used, int *returned,
+                        int len);
        void (*halt_input) (int dev);
        void (*halt_output) (int dev);
        void (*trigger) (int dev, int bits);
index d0498b08ee0fc3f8f7ab8a2a9d82bdf0b68b865b..014d6a73cc447b5bdafb25a155f4995f1af5c6c4 100644 (file)
  *                   determine if it was woken up by the expiring timeout or by
  *                   an explicit wake_up. The return value from schedule_timeout
  *                  can be used instead; if 0, the wakeup was due to the timeout.
+ *
+ * Rob Riggs           Added persistent DMA buffers (1998/10/17)
  */
 #include <linux/config.h>
 
 #define BE_CONSERVATIVE
@@ -28,6 +31,9 @@
 
 #if defined(CONFIG_AUDIO) || defined(CONFIG_GUS)
 
+#define DMAP_FREE_ON_CLOSE      0
+#define DMAP_KEEP_ON_CLOSE      1
+extern int sound_dmap_flag;
 
 static void dma_reset_output(int dev);
 static void dma_reset_input(int dev);
@@ -212,7 +218,8 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap
        disable_dma(dmap->dma);
        release_dma_lock(flags);
        
-       sound_free_dmap(dmap);
+       if (sound_dmap_flag == DMAP_FREE_ON_CLOSE)
+               sound_free_dmap(dmap);
 }
 
 
@@ -732,7 +739,7 @@ static int output_sleep(int dev, int dontblock)
         * Wait for free space
         */
        if (signal_pending(current))
-               return -EIO;
+               return -EINTR;
        timeout = (adev->go && !(dmap->flags & DMA_NOTIMEOUT));
        if (timeout) 
                timeout_value = dmabuf_timeout(dmap);
@@ -1009,8 +1016,8 @@ void DMAbuf_outputintr(int dev, int notify_only)
                unsigned long f;
                
                f=claim_dma_lock();
-               clear_dma_ff(chan);
                disable_dma(dmap->dma);
+               clear_dma_ff(chan);
                pos = dmap->bytes_in_use - get_dma_residue(chan);
                enable_dma(dmap->dma);
                release_dma_lock(f);
@@ -1104,8 +1111,8 @@ void DMAbuf_inputintr(int dev)
                unsigned long f;
                
                f=claim_dma_lock();
-               clear_dma_ff(chan);
                disable_dma(dmap->dma);
+               clear_dma_ff(chan);
                pos = dmap->bytes_in_use - get_dma_residue(chan);
                enable_dma(dmap->dma);
                release_dma_lock(f);
@@ -1181,6 +1188,13 @@ void DMAbuf_init(int dev, int dma1, int dma2)
                                adev->dmap_in->dma = dma2;
                        }
                }
+               /* Persistent DMA buffers allocated here */
+               if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) {
+                       if (adev->dmap_in->raw_buf == NULL)
+                               sound_alloc_dmap(adev->dmap_in);
+                       if (adev->dmap_out->raw_buf == NULL)
+                               sound_alloc_dmap(adev->dmap_out);
+               }
        }
 }
 
@@ -1251,12 +1265,13 @@ void DMAbuf_deinit(int dev)
        /* This routine is called when driver is being unloaded */
        if (!adev)
                return;
-#ifdef RUNTIME_DMA_ALLOC
-       sound_free_dmap(adev->dmap_out);
 
-       if (adev->flags & DMA_DUPLEX)
-               sound_free_dmap(adev->dmap_in);
-#endif
+       /* Persistent DMA buffers deallocated here */
+       if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) {
+               sound_free_dmap(adev->dmap_out);
+               if (adev->flags & DMA_DUPLEX)
+                       sound_free_dmap(adev->dmap_in);
+       }
 }
 
 #endif
index f74632927a14d156fa2d2be355831c51195b156d..56aa9e9992c3be7a28d385be6a9e41a0fec37d89 100644 (file)
@@ -816,7 +816,7 @@ static struct sound_queue sq;
 #define ONE_SECOND     HZ      /* in jiffies (100ths of a second) */
 #define NO_TIME_LIMIT  0xffffffff
 #define SLEEP(queue, time_limit) \
-       interruptible_sleep_on(&queue, (time_limit));
+       interruptible_sleep_on_timeout(&queue, (time_limit));
 #define WAKE_UP(queue) (wake_up_interruptible(&queue))
 
 /*
index e1af44cef39953f1a134c4293e7fd5d92d9e2624..489c2c7c08c09ca6ce1c47c2eb65a5345394f3f3 100644 (file)
@@ -834,7 +834,6 @@ int probe_mad16_mpu(struct address_info *hw_config)
 
 void unload_mad16(struct address_info *hw_config)
 {
-       int mixer = audio_devs[hw_config->slots[0]]->mixer_dev;
        ad1848_unload(hw_config->io_base + 4,
                        hw_config->irq,
                        hw_config->dma,
index 794036b81046e8e0df0d1e4b1a207f61b149d241..2b2be83d589a5618cf06d6d7778f19edcadcfc86 100644 (file)
@@ -48,7 +48,6 @@ extern void sound_close_dma(int chn);
 
 extern void reprogram_timer(void);
 
-#define RUNTIME_DMA_ALLOC
 #define USE_AUTOINIT_DMA
 
 extern caddr_t sound_mem_blocks[1024];
index 49bf2b1263e5e044f908222cdb5e28555813567f..dc864646e14ce68830756513eb7253c0e164c11c 100644 (file)
@@ -87,14 +87,14 @@ typedef struct sb_devc {
 
        /* State variables */
           int opened;
-    /* new audio fields for full duplex support */
-       int fullduplex;
-       int duplex;
+       /* new audio fields for full duplex support */
+          int fullduplex;
+          int duplex;
           int speed, bits, channels;
           volatile int irq_ok;
           volatile int intr_active, irq_mode;
-    /* duplicate audio fields for full duplex support */
-          volatile int intr_active_2, irq_mode_2;
+       /* duplicate audio fields for full duplex support */
+          volatile int intr_active_16, irq_mode_16;
 
        /* Mixer fields */
           int *levels;
@@ -110,12 +110,12 @@ typedef struct sb_devc {
           int      trg_bytes;
           int      trg_intrflag;
           int      trg_restart;
-    /* duplicate audio fields for full duplex support */
-          unsigned long trg_buf_2;
-          int      trigger_bits_2;
-          int      trg_bytes_2;
-          int      trg_intrflag_2;
-          int      trg_restart_2;
+       /* duplicate audio fields for full duplex support */
+          unsigned long trg_buf_16;
+          int      trigger_bits_16;
+          int      trg_bytes_16;
+          int      trg_intrflag_16;
+          int      trg_restart_16;
 
           unsigned char tconst;
           int my_dev;
index ed6e11fc3954b5687be71bee872b8cd5b9fce136..b14924e4e68cdd8402dfe41f5320dab88c89cd68 100644 (file)
@@ -51,7 +51,7 @@ static int sb_audio_open(int dev, int mode)
                  restore_flags(flags);
                  return -EBUSY;
        }
-    if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex)
+       if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex)
        {
                if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit"))
                {
@@ -63,10 +63,9 @@ static int sb_audio_open(int dev, int mode)
        restore_flags(flags);
 
        devc->irq_mode = IMODE_NONE;
-    devc->irq_mode_2 = IMODE_NONE;
-    devc->intr_active_2 = 0;
-    devc->fullduplex = devc->duplex &&
-        ((mode & OPEN_READ) && (mode & OPEN_WRITE));
+       devc->irq_mode_16 = IMODE_NONE;
+       devc->fullduplex = devc->duplex &&
+               ((mode & OPEN_READ) && (mode & OPEN_WRITE));
        sb_dsp_reset(devc);
 
        /* The ALS007 seems to require that the DSP be removed from the output */
@@ -92,11 +91,11 @@ static void sb_audio_close(int dev)
 {
        sb_devc *devc = audio_devs[dev]->devc;
 
-    audio_devs[dev]->dmap_out->dma = devc->dma8;
-    audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ?
-        devc->dma16 : devc->dma8;
+       audio_devs[dev]->dmap_out->dma = devc->dma8;
+       audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ?
+               devc->dma16 : devc->dma8;
 
-    if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex)
+       if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex)
                sound_close_dma(devc->dma16);
 
        /* For ALS007, turn DSP output back on if closing the device for read */
@@ -114,34 +113,40 @@ static void sb_set_output_parms(int dev, unsigned long buf, int nr_bytes,
 {
        sb_devc *devc = audio_devs[dev]->devc;
 
-    if( !devc->fullduplex || devc->bits == AFMT_S16_LE) {
-        devc->trg_buf = buf;
-        devc->trg_bytes = nr_bytes;
-        devc->trg_intrflag = intrflag;
-        devc->irq_mode = IMODE_OUTPUT;
-    } else {
-        devc->trg_buf_2 = buf;
-        devc->trg_bytes_2 = nr_bytes;
-        devc->trg_intrflag_2 = intrflag;
-        devc->irq_mode_2 = IMODE_OUTPUT;
-    }
+       if (!devc->fullduplex || devc->bits == AFMT_S16_LE)
+       {
+               devc->trg_buf = buf;
+               devc->trg_bytes = nr_bytes;
+               devc->trg_intrflag = intrflag;
+               devc->irq_mode = IMODE_OUTPUT;
+       }
+       else
+       {
+               devc->trg_buf_16 = buf;
+               devc->trg_bytes_16 = nr_bytes;
+               devc->trg_intrflag_16 = intrflag;
+               devc->irq_mode_16 = IMODE_OUTPUT;
+       }
 }
 
 static void sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag)
 {
        sb_devc *devc = audio_devs[dev]->devc;
 
-    if( !devc->fullduplex || devc->bits != AFMT_S16_LE) {
-        devc->trg_buf = buf;
-        devc->trg_bytes = count;
-        devc->trg_intrflag = intrflag;
-        devc->irq_mode = IMODE_INPUT;
-    } else {
-        devc->trg_buf_2 = buf;
-        devc->trg_bytes_2 = count;
-        devc->trg_intrflag_2 = intrflag;
-        devc->irq_mode_2 = IMODE_INPUT;
-    }
+       if (!devc->fullduplex || devc->bits != AFMT_S16_LE)
+       {
+               devc->trg_buf = buf;
+               devc->trg_bytes = count;
+               devc->trg_intrflag = intrflag;
+               devc->irq_mode = IMODE_INPUT;
+       }
+       else
+       {
+               devc->trg_buf_16 = buf;
+               devc->trg_bytes_16 = count;
+               devc->trg_intrflag_16 = intrflag;
+               devc->irq_mode_16 = IMODE_INPUT;
+       }
 }
 
 /*
@@ -854,17 +859,23 @@ static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
        sb_devc *devc = audio_devs[dev]->devc;
 
-    if( !devc->fullduplex) {
-        audio_devs[dev]->dmap_out->dma =
-            audio_devs[dev]->dmap_in->dma =
-            devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8;
-    } else if( devc->bits == AFMT_S16_LE) {
-        audio_devs[dev]->dmap_out->dma = devc->dma8;
-        audio_devs[dev]->dmap_in->dma = devc->dma16;
-    } else {
-        audio_devs[dev]->dmap_out->dma = devc->dma16;
-        audio_devs[dev]->dmap_in->dma = devc->dma8;
-    }
+       if (!devc->fullduplex)
+       {
+               audio_devs[dev]->dmap_out->dma =
+                       audio_devs[dev]->dmap_in->dma =
+                               devc->bits == AFMT_S16_LE ?
+                                       devc->dma16 : devc->dma8;
+       }
+       else if (devc->bits == AFMT_S16_LE)
+       {
+               audio_devs[dev]->dmap_out->dma = devc->dma8;
+               audio_devs[dev]->dmap_in->dma = devc->dma16;
+       }
+       else
+       {
+               audio_devs[dev]->dmap_out->dma = devc->dma16;
+               audio_devs[dev]->dmap_in->dma = devc->dma8;
+       }
 
        devc->trigger_bits = 0;
        return 0;
@@ -874,17 +885,23 @@ static int sb16_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
        sb_devc *devc = audio_devs[dev]->devc;
 
-    if( !devc->fullduplex) {
-        audio_devs[dev]->dmap_out->dma =
-            audio_devs[dev]->dmap_in->dma =
-            devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8;
-    } else if( devc->bits == AFMT_S16_LE) {
-        audio_devs[dev]->dmap_out->dma = devc->dma8;
-        audio_devs[dev]->dmap_in->dma = devc->dma16;
-    } else {
-        audio_devs[dev]->dmap_out->dma = devc->dma16;
-        audio_devs[dev]->dmap_in->dma = devc->dma8;
-    }
+       if (!devc->fullduplex)
+       {
+               audio_devs[dev]->dmap_out->dma =
+                       audio_devs[dev]->dmap_in->dma =
+                               devc->bits == AFMT_S16_LE ?
+                                       devc->dma16 : devc->dma8;
+       }
+       else if (devc->bits == AFMT_S16_LE)
+       {
+               audio_devs[dev]->dmap_out->dma = devc->dma8;
+               audio_devs[dev]->dmap_in->dma = devc->dma16;
+       }
+       else
+       {
+               audio_devs[dev]->dmap_out->dma = devc->dma16;
+               audio_devs[dev]->dmap_in->dma = devc->dma8;
+       }
 
        devc->trigger_bits = 0;
        return 0;
@@ -895,23 +912,27 @@ static void sb16_audio_output_block(int dev, unsigned long buf, int count,
 {
        unsigned long   flags, cnt;
        sb_devc        *devc = audio_devs[dev]->devc;
-    unsigned long   bits;
-
-    if( !devc->fullduplex || devc->bits == AFMT_S16_LE) {
-        devc->irq_mode = IMODE_OUTPUT;
-        devc->intr_active = 1;
-    } else {
-        devc->irq_mode_2 = IMODE_OUTPUT;
-        devc->intr_active_2 = 1;
-    }
-
-    /* save value */
-    save_flags (flags);
-    cli ();
-    bits = devc->bits;
-    if( devc->fullduplex)
-        devc->bits = (devc->bits == AFMT_S16_LE) ? AFMT_U8 : AFMT_S16_LE;
-    restore_flags (flags);
+       unsigned long   bits;
+
+       if (!devc->fullduplex || devc->bits == AFMT_S16_LE)
+       {
+               devc->irq_mode = IMODE_OUTPUT;
+               devc->intr_active = 1;
+       }
+       else
+       {
+               devc->irq_mode_16 = IMODE_OUTPUT;
+               devc->intr_active_16 = 1;
+       }
+
+       /* save value */
+       save_flags (flags);
+       cli ();
+       bits = devc->bits;
+       if (devc->fullduplex)
+               devc->bits = (devc->bits == AFMT_S16_LE) ?
+                       AFMT_U8 : AFMT_S16_LE;
+       restore_flags (flags);
 
        cnt = count;
        if (devc->bits == AFMT_S16_LE)
@@ -933,8 +954,8 @@ static void sb16_audio_output_block(int dev, unsigned long buf, int count,
        sb_dsp_command(devc, (unsigned char) (cnt & 0xff));
        sb_dsp_command(devc, (unsigned char) (cnt >> 8));
 
-    /* restore real value after all programming */
-    devc->bits = bits;
+       /* restore real value after all programming */
+       devc->bits = bits;
        restore_flags(flags);
 }
 
@@ -943,13 +964,16 @@ static void sb16_audio_start_input(int dev, unsigned long buf, int count, int in
        unsigned long   flags, cnt;
        sb_devc        *devc = audio_devs[dev]->devc;
 
-    if( !devc->fullduplex || devc->bits != AFMT_S16_LE) {
-        devc->irq_mode = IMODE_INPUT;
-        devc->intr_active = 1;
-    } else {
-        devc->irq_mode_2 = IMODE_INPUT;
-        devc->intr_active_2 = 1;
-    }
+       if (!devc->fullduplex || devc->bits != AFMT_S16_LE)
+       {
+               devc->irq_mode = IMODE_INPUT;
+               devc->intr_active = 1;
+       }
+       else
+       {
+               devc->irq_mode_16 = IMODE_INPUT;
+               devc->intr_active_16 = 1;
+       }
 
        cnt = count;
        if (devc->bits == AFMT_S16_LE)
@@ -978,122 +1002,138 @@ static void sb16_audio_trigger(int dev, int bits)
 {
        sb_devc *devc = audio_devs[dev]->devc;
 
-    int bits_2 = bits & devc->irq_mode_2;
+       int bits_16 = bits & devc->irq_mode_16;
        bits &= devc->irq_mode;
 
-       if (!bits)
+       if (!bits && !bits_16)
                sb_dsp_command(devc, 0xd0);     /* Halt DMA */
        else
        {
-        if( bits) {
-            switch (devc->irq_mode)
-            {
-                               case IMODE_INPUT:
-                    sb16_audio_start_input(dev, devc->trg_buf,
-                                           devc->trg_bytes,
-                                           devc->trg_intrflag);
-                    break;
-
-                           case IMODE_OUTPUT:
-                    sb16_audio_output_block(dev, devc->trg_buf,
-                                            devc->trg_bytes,
-                                            devc->trg_intrflag);
-                    break;
-            }
-        }
-        if( bits_2) {
-            switch (devc->irq_mode_2)
-            {
-                case IMODE_INPUT:
-                    sb16_audio_start_input (dev, devc->trg_buf_2,
-                                            devc->trg_bytes_2,
-                                            devc->trg_intrflag_2);
-                    break;
-                case IMODE_OUTPUT:
-                    sb16_audio_output_block (dev, devc->trg_buf_2,
-                                             devc->trg_bytes_2,
-                                             devc->trg_intrflag_2);
-                    break;
-            }
-        }
+               if (bits)
+               {
+                       switch (devc->irq_mode)
+                       {
+                               case IMODE_INPUT:
+                                       sb16_audio_start_input(dev,
+                                                       devc->trg_buf,
+                                                       devc->trg_bytes,
+                                                       devc->trg_intrflag);
+                                       break;
+
+                               case IMODE_OUTPUT:
+                                       sb16_audio_output_block(dev,
+                                                       devc->trg_buf,
+                                                       devc->trg_bytes,
+                                                       devc->trg_intrflag);
+                                       break;
+                       }
+               }
+               if (bits_16)
+               {
+                       switch (devc->irq_mode_16)
+                       {
+                               case IMODE_INPUT:
+                                       sb16_audio_start_input(dev,
+                                                       devc->trg_buf_16,
+                                                       devc->trg_bytes_16,
+                                                       devc->trg_intrflag_16);
+                                       break;
+
+                               case IMODE_OUTPUT:
+                                       sb16_audio_output_block(dev,
+                                                       devc->trg_buf_16,
+                                                       devc->trg_bytes_16,
+                                                       devc->trg_intrflag_16);
+                                       break;
+                       }
+               }
        }
 
-       devc->trigger_bits = bits | bits_2;
+       devc->trigger_bits = bits | bits_16;
 }
 
 static unsigned char lbuf8[2048];
 static signed short *lbuf16 = (signed short *)lbuf8;
 #define LBUFCOPYSIZE 1024
 static void
-sb16_copy_from_user( int dev,
-                     char *localbuf, int localoffs,
-                     const char *userbuf, int useroffs,
-                     int max_in, int max_out,
-                     int *used, int *returned,
-                     int len)
+sb16_copy_from_user(int dev,
+               char *localbuf, int localoffs,
+               const char *userbuf, int useroffs,
+               int max_in, int max_out,
+               int *used, int *returned,
+               int len)
 {
-  sb_devc        *devc = audio_devs[dev]->devc;
-  int i, c, p, locallen;
-  unsigned char *buf8;
-  signed short *buf16;
-
-  /* if not duplex no conversion */
-  if( !devc->fullduplex) {
-    copy_from_user( localbuf + localoffs, userbuf + useroffs, len);
-    *used = len;
-    *returned = len;
-  } else if( devc->bits == AFMT_S16_LE) {
-    /* 16 -> 8 */
-    /* max_in >> 1, max number of samples in ( 16 bits ) */
-    /* max_out, max number of samples out ( 8 bits ) */
-    /* len, number of samples that will be taken ( 16 bits )*/
-    /* c, count of samples remaining in buffer ( 16 bits )*/
-    /* p, count of samples already processed ( 16 bits )*/
-    len = ( (max_in >> 1) > max_out) ? max_out : (max_in >> 1);
-    c = len;
-    p = 0;
-    buf8 = (unsigned char *)(localbuf + localoffs);
-    while( c) {
-      locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
-      /* << 1 in order to get 16 bit samples */
-      copy_from_user( lbuf16,
-                 userbuf+useroffs + (p << 1),
-                 locallen << 1);
-      for( i = 0; i < locallen; i++) {
-        buf8[p+i] = ~((lbuf16[i] >> 8) & 0xff) ^ 0x80;
-      }
-      c -= locallen; p += locallen;
-    }
-    /* used = ( samples * 16 bits size ) */
-    *used = len << 1;
-    /* returned = ( samples * 8 bits size ) */
-    *returned = len;
-  } else {
-    /* 8 -> 16 */
-    /* max_in, max number of samples in ( 8 bits ) */
-    /* max_out >> 1, max number of samples out ( 16 bits ) */
-    /* len, number of samples that will be taken ( 8 bits )*/
-    /* c, count of samples remaining in buffer ( 8 bits )*/
-    /* p, count of samples already processed ( 8 bits )*/
-    len = max_in > (max_out >> 1) ? (max_out >> 1) : max_in;
-    c = len;
-    p = 0;
-    buf16 = (signed short *)(localbuf + localoffs);
-    while( c) {
-      locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
-      copy_from_user( lbuf8,
-                 userbuf+useroffs + p,
-                 locallen);
-      for( i = 0; i < locallen; i++) {
-        buf16[p+i] = (~lbuf8[i] ^ 0x80) << 8;
-      }
-      c -= locallen; p += locallen;
-    }
-    /* used = ( samples * 8 bits size ) */
-    *used = len;
-    /* returned = ( samples * 16 bits size ) */
-    *returned = len << 1;
-  }
+       sb_devc       *devc = audio_devs[dev]->devc;
+       int           i, c, p, locallen;
+       unsigned char *buf8;
+       signed short  *buf16;
+
+       /* if not duplex no conversion */
+       if (!devc->fullduplex)
+       {
+               copy_from_user (localbuf + localoffs, userbuf + useroffs, len);
+               *used = len;
+               *returned = len;
+       }
+       else if (devc->bits == AFMT_S16_LE)
+       {
+               /* 16 -> 8 */
+               /* max_in >> 1, max number of samples in ( 16 bits ) */
+               /* max_out, max number of samples out ( 8 bits ) */
+               /* len, number of samples that will be taken ( 16 bits )*/
+               /* c, count of samples remaining in buffer ( 16 bits )*/
+               /* p, count of samples already processed ( 16 bits )*/
+               len = ( (max_in >> 1) > max_out) ? max_out : (max_in >> 1);
+               c = len;
+               p = 0;
+               buf8 = (unsigned char *)(localbuf + localoffs);
+               while (c)
+               {
+                       locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
+                       /* << 1 in order to get 16 bit samples */
+                       copy_from_user (lbuf16,
+                                       userbuf+useroffs + (p << 1),
+                                       locallen << 1);
+                       for (i = 0; i < locallen; i++)
+                       {
+                               buf8[p+i] = ~((lbuf16[i] >> 8) & 0xff) ^ 0x80;
+                       }
+                       c -= locallen; p += locallen;
+               }
+               /* used = ( samples * 16 bits size ) */
+               *used = len << 1;
+               /* returned = ( samples * 8 bits size ) */
+               *returned = len;
+       }
+       else
+       {
+               /* 8 -> 16 */
+               /* max_in, max number of samples in ( 8 bits ) */
+               /* max_out >> 1, max number of samples out ( 16 bits ) */
+               /* len, number of samples that will be taken ( 8 bits )*/
+               /* c, count of samples remaining in buffer ( 8 bits )*/
+               /* p, count of samples already processed ( 8 bits )*/
+               len = max_in > (max_out >> 1) ? (max_out >> 1) : max_in;
+               c = len;
+               p = 0;
+               buf16 = (signed short *)(localbuf + localoffs);
+               while (c)
+               {
+                       locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
+                       copy_from_user (lbuf8,
+                                       userbuf+useroffs + p,
+                                       locallen);
+                       for (i = 0; i < locallen; i++)
+                       {
+                               buf16[p+i] = (~lbuf8[i] ^ 0x80) << 8;
+                       }
+                       c -= locallen; p += locallen;
+               }
+               /* used = ( samples * 8 bits size ) */
+               *used = len;
+               /* returned = ( samples * 16 bits size ) */
+               *returned = len << 1;
+       }
 }
 
 
@@ -1208,7 +1248,7 @@ static struct audio_driver sb16_audio_driver =    /* SB16 */
        sb16_audio_prepare_for_output,
        sb1_audio_halt_xfer,
        NULL,                   /* local_qlen */
-       sb16_copy_from_user,                    /* copy_from_user */
+       sb16_copy_from_user,    /* copy_from_user */
        NULL,
        NULL,
        sb16_audio_trigger,
@@ -1244,7 +1284,6 @@ void sb_audio_init(sb_devc * devc, char *name)
 
        struct audio_driver *driver = &sb1_audio_driver;
 
-    devc->duplex = 0;
        switch (devc->model)
        {
                case MDL_SB1:   /* SB1.0 or SB 1.5 */
@@ -1283,10 +1322,11 @@ void sb_audio_init(sb_devc * devc, char *name)
                        DDB(printk("Will use SB16 driver\n"));
                        audio_flags = DMA_AUTOMODE;
                        format_mask |= AFMT_S16_LE;
-            if( devc->dma8 != devc->dma16 && devc->dma16 != -1) {
-                audio_flags |= DMA_DUPLEX;
-                devc->duplex = 1;
-            }
+                       if (devc->dma8 != devc->dma16 && devc->dma16 != -1)
+                       {
+                               audio_flags |= DMA_DUPLEX;
+                               devc->duplex = 1;
+                       }
                        driver = &sb16_audio_driver;
                        break;
 
@@ -1300,8 +1340,7 @@ void sb_audio_init(sb_devc * devc, char *name)
                                name,driver, sizeof(struct audio_driver),
                                audio_flags, format_mask, devc,
                                devc->dma8,
-                (devc->dma8 != devc->dma16 && devc->dma16 != -1)
-                     ? devc->dma16 : devc->dma8)) < 0)
+                               devc->duplex ? devc->dma16 : devc->dma8) < 0))
        {
                  printk(KERN_ERR "Sound Blaster:  unable to install audio.\n");
                  return;
index caa8aa381a3b50b5fc704ee61ffa31a8519f1b01..a64e180cdbb9d76195a8ab02c2a21ebe60917f1c 100644 (file)
@@ -168,17 +168,27 @@ static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
                                /* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */
                                ;
                }
-    } else if (devc->intr_active_2 && (src & 0x02)) {
-        switch (devc->irq_mode_2)
-        {
-            case IMODE_OUTPUT:
-                DMAbuf_outputintr (devc->dev, 1);
-                break;
-            case IMODE_INPUT:
-                DMAbuf_inputintr (devc->dev);
-                break;
-        }
-    }
+       }
+       else if (devc->intr_active_16 && (src & 0x02))
+       {
+               switch (devc->irq_mode_16)
+               {
+                       case IMODE_OUTPUT:
+                               DMAbuf_outputintr(devc->dev, 1);
+                               break;
+
+                       case IMODE_INPUT:
+                               DMAbuf_inputintr(devc->dev);
+                               break;
+
+                       case IMODE_INIT:
+                               break;
+
+                       default:
+                               /* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */
+                               ;
+               }
+       }
        /*
         * Acknowledge interrupts 
         */
@@ -605,6 +615,7 @@ int sb_dsp_detect(struct address_info *hw_config)
        sb_devc sb_info;
        sb_devc *devc = &sb_info;
 
+       memset((char *) &sb_info, 0, sizeof(sb_info));  /* Zero everything */
        sb_info.my_mididev = -1;
        sb_info.my_mixerdev = -1;
        sb_info.my_dev = -1;
@@ -621,7 +632,6 @@ int sb_dsp_detect(struct address_info *hw_config)
 #endif
                return 0;
        }
-       memset((char *) &sb_info, 0, sizeof(sb_info));  /* Zero everything */
 
        devc->type = hw_config->card_subtype;
 
@@ -971,7 +981,7 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
                        /* We don't have to do this bit any more the UART401 is its own
                                master  -- Krzysztof Halasa */
                        /* But we have to do it, if UART401 is not detected */
-                       if (!sbmpu && devc->my_mididev)
+                       if (!sbmpu)
                                sound_unload_mididev(devc->my_mididev);
                        sound_unload_audiodev(devc->my_dev);
                }
index f8fefca172c62b64691aa19b4532c1ed1dd83ce4..7f61e6e0c7d94c02d61ba4a20b0c30d060c31cab 100644 (file)
@@ -201,7 +201,7 @@ MIX_ENT(SOUND_MIXER_SYNTH,  0x66, 7, 4, 0x66, 3, 4),
 MIX_ENT(SOUND_MIXER_PCM,       0x64, 7, 4, 0x64, 3, 4),
 MIX_ENT(SOUND_MIXER_SPEAKER,   0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_LINE,      0x6e, 7, 4, 0x6e, 3, 4),
-MIX_ENT(SOUND_MIXER_MIC,       0x6a, 6, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_MIC,       0x6a, 2, 3, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_CD,                0x68, 7, 4, 0x68, 3, 4),
 MIX_ENT(SOUND_MIXER_IMIX,      0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_ALTPCM,    0x00, 0, 0, 0x00, 0, 0),
index e92aa8321b0ad019db6c5a51d8d32a1e5d0564f9..baff3e5ccc7a13c11fbd4daa5c03a251ceddd848 100644 (file)
@@ -29,7 +29,7 @@
 static void sleep( unsigned howlong )
 {
        current->state   = TASK_INTERRUPTIBLE;
-       schedule(howlong);
+       schedule_timeout(howlong);
 }
 
 #define DPORT 0x80
@@ -108,9 +108,7 @@ int probe_sgalaxy( struct address_info *ai )
 
        sleep( HZ/10 );
 
-       if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) )
-               return 1;
-       return 0;
+       return probe_ms_sound(ai);
 }
 
 void attach_sgalaxy( struct address_info *ai )
index 1fbb368d86e09efe013474d7a8cd408ba4475d12..3e3abd044aa12664d403c193340abe126f703964 100644 (file)
@@ -15,6 +15,8 @@
  *                   integrated sound_switch.c
  * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat,
  *                   which should disappear in the near future)
+ *
+ * Rob Riggs           Added persistent DMA buffers support (1998/10/17)
  */
 
 #include <linux/config.h>
@@ -64,6 +66,9 @@ static int      is_unloading = 0;
 caddr_t         sound_mem_blocks[1024];
 int             sound_nblocks = 0;
 
+/* Persistent DMA buffers */
+int            sound_dmap_flag = 0;    /* Off by default */
+
 static int      soundcard_configured = 0;
 
 static char     dma_alloc_map[MAX_DMA_CHANNELS] =
@@ -848,7 +853,9 @@ static int      sound[20] = {
 #ifdef MODULE
 
 int traceinit = 0;
+static int dmabuf = 0;
 MODULE_PARM(traceinit, "i");
+MODULE_PARM(dmabuf, "i");
 
 int init_module(void)
 {
@@ -874,6 +881,10 @@ int init_module(void)
                printk(KERN_ERR "sound: driver already loaded/included in kernel\n");
                return err;
        }
+
+       /* Protecting the innocent */
+       sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
+
        chrdev_registered = 1;
        soundcard_init();
 
index 3300795ea9dda78d10e5acf740620172367e73b3..b2e33ab1a2000762cf0117b949778ddcbc1548bf 100644 (file)
@@ -2055,14 +2055,12 @@ wavefront_open (int dev, int mode)
        return (0);
 }
 
-static void
-wavefront_close (int dev)
-
+static void wavefront_close (int dev)
 {
        struct wf_config *hw = &wavefront_configuration;
-       int i;
 
 #ifdef WF_STATS
+       int i;
        printk ("Status during loop: %ld\n", hw->status_found_during_loop);
        for (i = 0; i < 4; i++) {
                printk ("Status during sleep[%d]: %ld\n",
@@ -2075,42 +2073,36 @@ wavefront_close (int dev)
        return;
 }
 
-static void
-wavefront_aftertouch (int dev, int channel, int pressure)
+static void wavefront_aftertouch (int dev, int channel, int pressure)
 {
        midi_synth_aftertouch (wavefront_configuration.mididev,channel,pressure);
 };
 
-static void
-wavefront_bender (int dev, int chn, int value)
+static void wavefront_bender (int dev, int chn, int value)
 {
        midi_synth_bender (wavefront_configuration.mididev, chn, value);
 };
 
-static void
-wavefront_controller (int dev, int channel, int ctrl_num, int value)
+static void wavefront_controller (int dev, int channel, int ctrl_num, int value)
 {
        if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value);
        midi_synth_controller (wavefront_configuration.mididev,
                               channel,ctrl_num,value);
 };
 
-static void
-wavefront_panning(int dev, int channel, int pressure)
+static void wavefront_panning(int dev, int channel, int pressure)
 {
        midi_synth_controller (wavefront_configuration.mididev,
                               channel,CTL_PAN,pressure);
 };
 
-static int
-wavefront_set_instr (int dev, int channel, int instr_no)
+static int wavefront_set_instr (int dev, int channel, int instr_no)
 {
        return(midi_synth_set_instr (wavefront_configuration.mididev,
                                     channel,instr_no));
 };
 
-static int
-wavefront_kill_note (int dev, int channel, int note, int volume)
+static int wavefront_kill_note (int dev, int channel, int note, int volume)
 {
        if (note==255)
                return (midi_synth_start_note (wavefront_configuration.mididev,
@@ -2119,8 +2111,7 @@ wavefront_kill_note (int dev, int channel, int note, int volume)
                                     channel, note, volume));
 };
 
-static int
-wavefront_start_note (int dev, int channel, int note, int volume)
+static int wavefront_start_note (int dev, int channel, int note, int volume)
 {
        if (note==255) {
                midi_synth_aftertouch (wavefront_configuration.mididev,
@@ -2140,13 +2131,11 @@ wavefront_start_note (int dev, int channel, int note, int volume)
        return(0);
 };
 
-static void
-wavefront_setup_voice (int dev, int voice, int chn)
+static void wavefront_setup_voice (int dev, int voice, int chn)
 {
 };
 
 static void wavefront_reset (int dev)
-
 {
        int i;
 
index 2333fd118d55c8e8904282a0060122ed2e9230b1..ee26fb1ec98afe9165946e2d639a9e804fdd76ec 100644 (file)
@@ -375,24 +375,25 @@ wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
        return 1;
 }
 
-void
-wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
+void wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
 {
        struct wf_mpu_config *devc;
-       int             dev;
+       int dev;
        static struct wf_mpu_config *isrc = 0;
-       int             n;
+       int n;
        struct midi_input_info *mi;
-       static int cnt = 0;
 
-       if (irq < 0 || irq > 15) {
+       if (irq < 0 || irq > 15) 
+       {
                printk (KERN_ERR "WF-MPU: bogus interrupt #%d", irq);
                return;
        }
        dev = irq2dev[irq];
        mi = &midi_devs[dev]->in_info;
-       if (mi->m_busy) return;
+       if (mi->m_busy)
+               return;
        mi->m_busy = 1;
+       
        sti (); 
 
        n = 50;
@@ -445,8 +446,7 @@ wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
        mi->m_busy = 0;
 }
 
-static int
-wf_mpu_open (int dev, int mode,
+static int wf_mpu_open (int dev, int mode,
             void            (*input) (int dev, unsigned char data),
             void            (*output) (int dev)
        )
index f4d37d3c5e7e2b1568d269e4d14c730214db994c..c7925b23538de9e1272660cee1bfa815f2a4859b 100644 (file)
@@ -116,7 +116,7 @@ do_aout_core_dump(long signr, struct pt_regs * regs)
 #else
        corefile[4] = '\0';
 #endif
-       dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC, 0600);
+       dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
        if (IS_ERR(dentry)) {
                dentry = NULL;
                goto end_coredump;
index db9b3c759fece9bbaa64f2ad69a5b656be7d554c..d0d2da81c26dc94d86eccc5634f3c2a39d53da0a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -485,10 +485,11 @@ static inline void release_old_signals(struct signal_struct * oldsig)
  * These functions flushes out all traces of the currently running executable
  * so that a new one can be started
  */
-
 static inline void flush_old_signals(struct task_struct *t)
 {
+#if 0
        flush_signals(t);
+#endif
        flush_signal_handlers(t);
 }
 
index c5af9d8e1d3814f137fb6509ace2880eb33c5e23..22af5533424490ec1c1e2ae006639b69830197b0 100644 (file)
@@ -70,7 +70,7 @@ struct inode_operations ext2_dir_inode_operations = {
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
-       ext2_truncate,          /* truncate */
+       NULL,                   /* truncate */
        ext2_permission,        /* permission */
        NULL                    /* smap */
 };
index b7e6eb209b02778b4181ba57613c35e4207d6ef8..49cb39c4d46cd4e982ebbb9d0cab5a3d314fcfd7 100644 (file)
@@ -135,7 +135,7 @@ lockd(struct svc_rqst *rqstp)
                 * during grace period).
                 */
                if (!nlmsvc_grace_period) {
-                       timeout = nlmsvc_retry_blocked() - jiffies;
+                       timeout = nlmsvc_retry_blocked();
                } else if (nlmsvc_grace_period < jiffies)
                        nlmsvc_grace_period = 0;
 
index ac650b5f3b09d69701183bdf12c449fdc5e0095e..b1f1f55888cdc0510751dfce4a600bd9f81f40df 100644 (file)
@@ -615,6 +615,7 @@ nlmsvc_retry_blocked(void)
        }
 
        if ((block = nlm_blocked) && block->b_when != NLM_NEVER)
-               return block->b_when;
-       return 0;
+               return (block->b_when - jiffies);
+
+       return MAX_SCHEDULE_TIMEOUT;
 }
index dc3e63347cf7d5b325c3d029135223d79fe5be40..d7db754ffdfc5057ca7eb3c3e0e8ef6e85952a9e 100644 (file)
@@ -55,7 +55,7 @@ struct inode_operations minix_dir_inode_operations = {
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
-       minix_truncate,         /* truncate */
+       NULL,                   /* truncate */
        NULL                    /* permission */
 };
 
index f8658f37f1130740abd98a5965c1061d17f2454f..f1e803bd29e3874edbc309861507ce3c3ae0a896 100644 (file)
@@ -505,12 +505,10 @@ nfs_writepage(struct file * file, struct page *page)
  * things with a page scheduled for an RPC call (e.g. invalidate it).
  */
 int
-nfs_updatepage(struct file *file, struct page *page, const char *buffer,
-                       unsigned long offset, unsigned int count, int sync)
+nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count, int sync)
 {
        struct dentry   *dentry = file->f_dentry;
        struct inode    *inode = dentry->d_inode;
-       u8              *page_addr = (u8 *) page_address(page);
        struct nfs_wreq *req;
        int             status = 0, page_locked = 1;
 
@@ -518,8 +516,6 @@ nfs_updatepage(struct file *file, struct page *page, const char *buffer,
                dentry->d_parent->d_name.name, dentry->d_name.name,
                count, page->offset+offset, sync);
 
-       set_bit(PG_locked, &page->flags);
-
        /*
         * Try to find a corresponding request on the writeback queue.
         * If there is one, we can be sure that this request is not
@@ -531,25 +527,14 @@ nfs_updatepage(struct file *file, struct page *page, const char *buffer,
         * page and retry the update.
         */
        if ((req = find_write_request(inode, page)) != NULL) {
-               if (update_write_request(req, offset, count)) {
-                       /* N.B. check for a fault here and cancel the req */
-                       /*
-                        *      SECURITY - copy_from_user must zero the
-                        *      rest of the data after a fault!
-                        */
-                       copy_from_user(page_addr + offset, buffer, count);
+               if (update_write_request(req, offset, count))
                        goto updated;
-               }
+
                dprintk("NFS:      wake up conflicting write request.\n");
                transfer_page_lock(req);
                return 0;
        }
 
-       /* Copy data to page buffer. */
-       status = -EFAULT;
-       if (copy_from_user(page_addr + offset, buffer, count))
-               goto done;
-
        /* If wsize is smaller than page size, update and write
         * page synchronously.
         */
@@ -566,6 +551,9 @@ nfs_updatepage(struct file *file, struct page *page, const char *buffer,
        page_locked = schedule_write_request(req, sync);
 
 updated:
+       if (req->wb_bytes == PAGE_SIZE)
+               set_bit(PG_uptodate, &page->flags);
+
        /*
         * If we wrote up to the end of the chunk, transmit request now.
         * We should be a bit more intelligent about detecting whether a
index e7e1e82469d5928c9da06e92154a2da4ee869e24..924a7c85230c811e4e583a5f5d687ddb04fa0120 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -626,7 +626,7 @@ out:
  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  * used by symlinks.
  */
-static int do_open(const char * filename, int flags, int mode, int fd)
+struct file *filp_open(const char * filename, int flags, int mode)
 {
        struct inode * inode;
        struct dentry * dentry;
@@ -667,8 +667,7 @@ static int do_open(const char * filename, int flags, int mode, int fd)
        }
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
-       fd_install(fd, f);
-       return 0;
+       return f;
 
 cleanup_all:
        if (f->f_mode & FMODE_WRITE)
@@ -679,7 +678,19 @@ cleanup_dentry:
 cleanup_file:
        put_filp(f);
 out:
-       return error;
+       return ERR_PTR(error);
+}
+
+/* should probably go into sys_open() */
+static int do_open(const char * filename, int flags, int mode, int fd)
+{
+       struct file * f;
+
+       f = filp_open(filename, flags, mode);
+       if (IS_ERR(f))
+               return PTR_ERR(f);
+       fd_install(fd, f);
+       return 0;
 }
 
 /*
index d5403a187b9566b30f20dd4aa55ffe219bb5bd73..63f7a6726ac50d79bf241a8de1702726f1caebbd 100644 (file)
  *                      <Jeff_Tranter@Mitel.COM>
  *
  * Bruno Haible      :  remove 4K limit for the maps file
- * <haible@ma2s2.mathematik.uni-karlsruhe.de>
+ *                     <haible@ma2s2.mathematik.uni-karlsruhe.de>
  *
  * Yves Arrouye      :  remove removal of trailing spaces in get_array.
  *                     <Yves.Arrouye@marin.fdn.fr>
-
+ *
  * Jerome Forissier  :  added per-CPU time information to /proc/stat
  *                      and /proc/<pid>/cpu extension
  *                      <forissier@isia.cma.fr>
  *                     Hans Marcus <crowbar@concepts.nl>
  *
  * aeb@cwi.nl        :  /proc/partitions
+ *
+ *
+ * Alan Cox         :  security fixes. 
+ *                     <Alan.Cox@linux.org>
+ *
  */
 
 #include <linux/types.h>
@@ -1326,6 +1331,46 @@ static long get_root_array(char * page, int type, char **start,
        return -EBADF;
 }
 
+static int process_unauthorized(int type, int pid)
+{
+       struct task_struct *p;
+       uid_t euid;     /* Save the euid keep the lock short */
+               
+       read_lock(&tasklist_lock);
+       
+       /*
+        *      Grab the lock, find the task, save the uid and 
+        *      check it has an mm still (ie its not dead)
+        */
+        
+       p = find_task_by_pid(pid);
+       if(p)
+       {
+               euid=p->euid;
+               if(!p->mm)      /* Scooby scooby doo where are you ? */
+                       p=NULL;
+       }
+               
+       read_unlock(&tasklist_lock);
+
+       if (!p)
+               return 1;
+
+       switch(type)
+       {
+               case PROC_PID_STATUS:
+               case PROC_PID_STATM:
+               case PROC_PID_STAT:
+               case PROC_PID_MAPS:
+               case PROC_PID_CMDLINE:
+                       return 0;       
+       }
+       if(capable(CAP_DAC_OVERRIDE) || current->fsuid == euid)
+               return 0;
+       return 1;
+}
+
+
 static int get_process_array(char * page, int pid, int type)
 {
        switch (type) {
@@ -1377,6 +1422,13 @@ static ssize_t array_read(struct file * file, char * buf,
        type &= 0x0000ffff;
        start = NULL;
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
+       
+       if (pid && process_unauthorized(type, pid))
+       {
+               free_page(page);
+               return -EIO;
+       }
+       
        if (dp->get_info)
                length = dp->get_info((char *)page, &start, *ppos,
                                      count, 0);
index f24b37e44f4aede9a834b53f631d2fd887736694..7f6920ebfbb1008a73afedd740d2875b199378e7 100644 (file)
@@ -827,6 +827,7 @@ static int proc_root_lookup(struct inode * dir, struct dentry * dentry)
                inode = proc_get_inode(dir->i_sb, ino, &proc_pid);
                if (!inode)
                        return -EINVAL;
+               inode->i_flags|=S_IMMUTABLE;
        }
 
        dentry->d_op = &proc_dentry_operations;
@@ -943,6 +944,7 @@ static int proc_root_readdir(struct file * filp,
 
        for (i = 0; i < nr_pids; i++) {
                int pid = pid_array[i];
+               ino_t ino = (pid << 16) + PROC_PID_INO;
                unsigned long j = PROC_NUMBUF;
 
                do {
@@ -951,7 +953,7 @@ static int proc_root_readdir(struct file * filp,
                        pid /= 10;
                } while (pid);
 
-               if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0)
+               if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0)
                        break;
                filp->f_pos++;
        }
index 328432d018de9d8513a92a3978f3058908976a86..4ea1e6efbacd6e42fb74cb408e53cc84703b1a44 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/fd.h>
 #include <linux/init.h>
 #include <linux/quotaops.h>
+#include <linux/acct.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -663,10 +664,7 @@ static int do_umount(kdev_t dev, int unmount_root, int flags)
         * are no quotas running any more. Just turn them on again.
         */
        DQUOT_OFF(dev);
-
-#ifdef CONFIG_BSD_PROCESS_ACCT
-       (void) acct_auto_close(dev);
-#endif
+       acct_auto_close(dev);
 
        /*
         * If we may have to abort operations to get out of this
@@ -971,6 +969,8 @@ static int do_remount(const char *dir,int flags,char *data)
                         */
                        shrink_dcache_sb(sb);
                        fsync_dev(sb->s_dev);
+                       if (flags & MS_RDONLY)
+                               acct_auto_close(sb->s_dev);
                        retval = do_remount_sb(sb, flags, data);
                }
                dput(dentry);
index ee99164fb56a0920239bdfb860463dfc2fe29343..9a1acc19e69006ec82881162d2014150dd859cf3 100644 (file)
@@ -62,7 +62,7 @@ struct inode_operations sysv_dir_inode_operations = {
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
-       sysv_truncate,          /* truncate */
+       NULL,                   /* truncate */
        NULL                    /* permission */
 };
 
index f3497dc7bda46eaed34653666979bacddaa53b17..170ffb10b6be37f05c28370c4c939505a2e31e08 100644 (file)
@@ -221,7 +221,7 @@ struct inode_operations ufs_dir_inode_operations = {
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        ufs_bmap,               /* bmap */
-       ufs_truncate,           /* truncate */
+       NULL,                   /* truncate */
        ufs_permission,         /* permission */
        NULL,                   /* smap */
 };
index 194d5f1b7a2bc905ee99404d3c7a8e88754a28ed..63837b1953cad893cbc226e306131c8a6a86f287 100644 (file)
@@ -5,9 +5,18 @@
 
 #ifndef __SMP__
 
-/* gcc 2.7.2 can crash initializing an empty structure.  */
-typedef struct { int dummy; } spinlock_t;
-#define SPIN_LOCK_UNLOCKED { 0 }
+/*
+ * Your basic spinlocks, allowing only a single CPU anywhere
+ *
+ * Gcc-2.7.x has a nasty bug with empty initializers.
+ */
+#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
+  typedef struct { } spinlock_t;
+  #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+#else
+  typedef struct { int gcc_is_buggy; } spinlock_t;
+  #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+#endif
 
 #define spin_lock_init(lock)                   ((void) 0)
 #define spin_lock(lock)                                ((void) 0)
@@ -29,9 +38,16 @@ typedef struct { int dummy; } spinlock_t;
  * can "mix" irq-safe locks - any writer needs to get a
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
+ *
+ * Gcc-2.7.x has a nasty bug with empty initializers.
  */
-typedef struct { int dummy; } rwlock_t;
-#define RW_LOCK_UNLOCKED { 0 }
+#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
+  typedef struct { } rwlock_t;
+  #define RW_LOCK_UNLOCKED (rwlock_t) { }
+#else
+  typedef struct { int gcc_is_buggy; } rwlock_t;
+  #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
+#endif
 
 #define read_lock(lock)                                ((void) 0)
 #define read_unlock(lock)                      ((void) 0)
index 4bc919b80568c8be4d63efc637042ed3d06e4bf6..748e331675e8f6adf76a758fc265a3b77cf2a8c0 100644 (file)
@@ -161,8 +161,6 @@ static __inline__ void disable_dma(unsigned int dmanr)
                dma_outb(dmanr | 4,  DMA1_MASK_REG);
        else
                dma_outb((dmanr & 3) | 4,  DMA2_MASK_REG);
-       /* I hate voodoo programming but .. */
-       udelay(20);
 }
 
 /* Clear the 'DMA Pointer Flip Flop'.
index 522718965cef454a700e9ce7661b5854754ded8a..64472231fef25506fa21e5e333de9b7f5d179dc3 100644 (file)
@@ -33,7 +33,9 @@
  * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
  */
 
-#define SHMMAX 0x1000000               /* max shared seg size (bytes) */
+#define SHMMAX 0x2000000               /* max shared seg size (bytes) */
+/* Try not to change the default shipped SHMMAX - people rely on it */
+
 #define SHMMIN 1 /* really PAGE_SIZE */        /* min shared seg size (bytes) */
 #define SHMMNI (1<<_SHM_ID_BITS)       /* max num of segs system wide */
 #define SHMALL                         /* max shm system wide (pages) */ \
index abcd0da25b17d0d687f610f132713a4c7ddd035b..6fa31e04084f2ba6469f9330b416bc5a8b7f71a6 100644 (file)
@@ -146,34 +146,36 @@ static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent
        if (_nr & 15) {                                 \
                _tmp = (_nr & 15) - 1;                  \
                asm volatile (                          \
-                       "1: movew %2@,%3@+; dbra %4,1b" \
+                       "1: movew %2@,%0@+; dbra %1,1b" \
+                       : "=a" (_buf), "=d" (_tmp)      \
+                       : "a" (_port), "0" (_buf),      \
+                         "1" (_tmp));                  \
+       }                                               \
+       if (_nr >> 4) {                                 \
+               _tmp = (_nr >> 4) - 1;                  \
+               asm volatile (                          \
+                       "1: "                           \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "movew %2@,%0@+; "              \
+                       "dbra %1,1b"                    \
                        : "=a" (_buf), "=d" (_tmp)      \
                        : "a" (_port), "0" (_buf),      \
                          "1" (_tmp));                  \
        }                                               \
-       _tmp = (_nr >> 4) - 1;                          \
-       asm volatile (                                  \
-               "1: "                                   \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "movew %2@,%3@+; "                      \
-               "dbra %4,1b"                            \
-               : "=a" (_buf), "=d" (_tmp)              \
-               : "a" (_port), "0" (_buf),              \
-                 "1" (_tmp));                          \
 })
 
 #define outsw(port, buf, nr) ({                                \
@@ -185,34 +187,36 @@ static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent
        if (_nr & 15) {                                 \
                _tmp = (_nr & 15) - 1;                  \
                asm volatile (                          \
-                       "1: movew %3@,%2@+; dbra %4,1b" \
+                       "1: movew %0@+,%2@; dbra %1,1b" \
+                       : "=a" (_buf), "=d" (_tmp)      \
+                       : "a" (_port), "0" (_buf),      \
+                         "1" (_tmp));                  \
+       }                                               \
+       if (_nr >> 4) {                                 \
+               _tmp = (_nr >> 4) - 1;                  \
+               asm volatile (                          \
+                       "1: "                           \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "movew %0@+,%2@; "              \
+                       "dbra %1,1b"                    \
                        : "=a" (_buf), "=d" (_tmp)      \
                        : "a" (_port), "0" (_buf),      \
                          "1" (_tmp));                  \
        }                                               \
-       _tmp = (_nr >> 4) - 1;                          \
-       asm volatile (                                  \
-               "1: "                                   \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "movew %3@+,%2@; "                      \
-               "dbra %4,1b"                            \
-               : "=a" (_buf), "=d" (_tmp)              \
-               : "a" (_port), "0" (_buf),              \
-                 "1" (_tmp));                          \
 })
 
 #ifdef CONFIG_ATARI
index 191c5d551299867c6b0105e0ed065e6a2e252128..a5f0abeb332db458d4085c2fafd4f62ddccab7c0 100644 (file)
@@ -336,9 +336,21 @@ static __inline__ void rs_receive_char( struct m68k_async_struct *info,
        if (tty->flip.count >= TTY_FLIPBUF_SIZE)
                return;
        tty->flip.count++;
-       if (err == TTY_BREAK) {
+       switch(err) {
+       case TTY_BREAK:
+               info->icount.brk++;
                if (info->flags & ASYNC_SAK)
                        do_SAK(tty);
+               break;
+       case TTY_PARITY:
+               info->icount.parity++;
+               break;
+       case TTY_OVERRUN:
+               info->icount.overrun++;
+               break;
+       case TTY_FRAME:
+               info->icount.frame++;
+               break;
        }
        *tty->flip.flag_buf_ptr++ = err;
        *tty->flip.char_buf_ptr++ = ch;
index e1c96a4c1285e04c929ee05f48f5201dd33b2f94..e20b183996e5bde928c76d7cf054209526df6c27 100644 (file)
@@ -76,8 +76,10 @@ struct acct
 #include <linux/config.h>
 
 #ifdef CONFIG_BSD_PROCESS_ACCT
+extern void acct_auto_close(kdev_t dev);
 extern int acct_process(long exitcode);
 #else
+#define acct_auto_close(x)     do { } while (0)
 #define acct_process(x)                do { } while (0)
 #endif
 
index 62d60076fdd3b07f7589446d726a053c3b720cf7..3a5adf06e51f4df98abcc63fc5fec0082aa16462 100644 (file)
@@ -605,8 +605,7 @@ struct inode_operations {
        void (*truncate) (struct inode *);
        int (*permission) (struct inode *, int);
        int (*smap) (struct inode *,int);
-       int (*updatepage) (struct file *, struct page *, const char *,
-                               unsigned long, unsigned int, int);
+       int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int);
        int (*revalidate) (struct dentry *);
 };
 
@@ -687,6 +686,7 @@ extern int do_truncate(struct dentry *, unsigned long);
 extern int get_unused_fd(void);
 extern void put_unused_fd(unsigned int);
 extern int close_fp(struct file *, fl_owner_t id);
+extern struct file *filp_open(const char *, int, int);
 
 extern char * getname(const char * filename);
 extern void putname(char * name);
index 22504204a89f32dee01640db26fcedaca446904a..f81844cf7b7dc66ffe14ef068e3c5d0021134e49 100644 (file)
@@ -46,6 +46,7 @@ NORET_TYPE void panic(const char * fmt, ...)
 NORET_TYPE void do_exit(long error_code)
        ATTRIB_NORET;
 extern unsigned long simple_strtoul(const char *,char **,unsigned int);
+extern long simple_strtol(const char *,char **,unsigned int);
 extern int sprintf(char * buf, const char * fmt, ...);
 extern int vsprintf(char *buf, const char *, va_list);
 
index b72ad4ed14db82c1c09f928abaabc8a8e64b0b88..e8df622ae8f9f70f57a0d356c826cfdb94d0d46d 100644 (file)
@@ -220,8 +220,7 @@ extern int  nfs_check_error(struct inode *);
 extern int  nfs_flush_dirty_pages(struct inode *, pid_t, off_t, off_t);
 extern int  nfs_truncate_dirty_pages(struct inode *, unsigned long);
 extern void nfs_invalidate_pages(struct inode *);
-extern int  nfs_updatepage(struct file *, struct page *, const char *,
-                       unsigned long, unsigned int, int);
+extern int  nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int, int);
 
 /*
  * linux/fs/nfs/read.c
index 4e41d457058b53bd1782b17df4d9e24ad4258d6c..bb9364e2b171d0428332bc5263125fa16f00f464 100644 (file)
@@ -458,7 +458,6 @@ extern unsigned long prof_shift;
 
 extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode));
 extern void FASTCALL(sleep_on(struct wait_queue ** p));
-extern void FASTCALL(sleep_on(struct wait_queue ** p));
 extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p));
 extern long FASTCALL(interruptible_sleep_on_timeout(struct wait_queue ** p,
                                                    signed long timeout));
index 008a974faefcce2b495e0c3d9a613ca064143e1f..20e3b9abfbd12f0705ea77c10cdc8e672c17cb6c 100644 (file)
@@ -44,99 +44,103 @@ struct __sysctl_args {
 
 /* For internal pattern-matching use only: */
 #ifdef __KERNEL__
-#define CTL_ANY                -1              /* Matches any name */
+#define CTL_ANY                -1      /* Matches any name */
 #define CTL_NONE       0
 #endif
 
 enum
 {
-/*1*/  CTL_KERN=1,             /* General kernel info and control */
-       CTL_VM,                 /* VM management */
-       CTL_NET,                /* Networking */
-       CTL_PROC,               /* Process info */
-       CTL_FS,                 /* Filesystems */
-       CTL_DEBUG,              /* Debugging */
-/*7*/  CTL_DEV,                /* Devices */
+       CTL_KERN=1,             /* General kernel info and control */
+       CTL_VM=2,               /* VM management */
+       CTL_NET=3,              /* Networking */
+       CTL_PROC=4,             /* Process info */
+       CTL_FS=5,               /* Filesystems */
+       CTL_DEBUG=6,            /* Debugging */
+       CTL_DEV=7,              /* Devices */
 };
 
 
 /* CTL_KERN names: */
 enum
 {
-/*1*/  KERN_OSTYPE=1,          /* string: system version */
-       KERN_OSRELEASE,         /* string: system release */
-       KERN_OSREV,             /* int: system revision */
-       KERN_VERSION,           /* string: compile time info */
-       KERN_SECUREMASK,        /* struct: maximum rights mask */
-       KERN_PROF,              /* table: profiling information */
-       KERN_NODENAME,
-/*8*/  KERN_DOMAINNAME,
-/*14*/ KERN_SECURELVL=14,      /* int: system security level */
-       KERN_PANIC,             /* int: panic timeout */
-/*16*/ KERN_REALROOTDEV,       /* real root device to mount after initrd */
-/*19*/ KERN_JAVA_INTERPRETER=19,/* path to Java(tm) interpreter */
-/*20*/ KERN_JAVA_APPLETVIEWER, /* path to Java(tm) appletviewer */
-       KERN_SPARC_REBOOT,      /* reboot command on Sparc */
-       KERN_CTLALTDEL,         /* int: allow ctl-alt-del to reboot */
-       KERN_PRINTK,            /* sturct: control printk logging parameters */
-       KERN_NAMETRANS,         /* Name translation */
-       KERN_PPC_HTABRECLAIM,   /* turn htab reclaimation on/off on PPC */
-       KERN_PPC_ZEROPAGED,     /* turn idle page zeroing on/off on PPC */
-       KERN_PPC_POWERSAVE_NAP, /* use nap mode for power saving */
-       KERN_PPC_L2CR,          /* l2cr register on PPC */
-       KERN_MODPROBE,
-/*29*/ KERN_SG_BIG_BUFF
+       KERN_OSTYPE=1,          /* string: system version */
+       KERN_OSRELEASE=2,       /* string: system release */
+       KERN_OSREV=3,           /* int: system revision */
+       KERN_VERSION=4,         /* string: compile time info */
+       KERN_SECUREMASK=5,      /* struct: maximum rights mask */
+       KERN_PROF=6,            /* table: profiling information */
+       KERN_NODENAME=7,
+       KERN_DOMAINNAME=8,
+
+       KERN_SECURELVL=14,      /* int: system security level */
+       KERN_PANIC=15,          /* int: panic timeout */
+       KERN_REALROOTDEV=16,    /* real root device to mount after initrd */
+
+       KERN_JAVA_INTERPRETER=19, /* path to Java(tm) interpreter */
+       KERN_JAVA_APPLETVIEWER=20, /* path to Java(tm) appletviewer */
+       KERN_SPARC_REBOOT=21,   /* reboot command on Sparc */
+       KERN_CTLALTDEL=22,      /* int: allow ctl-alt-del to reboot */
+       KERN_PRINTK=23,         /* struct: control printk logging parameters */
+       KERN_NAMETRANS=24,      /* Name translation */
+       KERN_PPC_HTABRECLAIM=25, /* turn htab reclaimation on/off on PPC */
+       KERN_PPC_ZEROPAGED=26,  /* turn idle page zeroing on/off on PPC */
+       KERN_PPC_POWERSAVE_NAP=27, /* use nap mode for power saving */
+       KERN_MODPROBE=28,
+       KERN_SG_BIG_BUFF=29,
+       KERN_ACCT=30,           /* BSD process accounting parameters */
+       KERN_PPC_L2CR=31,       /* l2cr register on PPC */
 };
 
 
 /* CTL_VM names: */
 enum
 {
-/*1*/  VM_SWAPCTL=1,           /* struct: Set vm swapping control */
-       VM_SWAPOUT,             /* int: Background pageout interval */
-       VM_FREEPG,              /* struct: Set free page thresholds */
-       VM_BDFLUSH,             /* struct: Control buffer cache flushing */
-       VM_OVERCOMMIT_MEMORY,   /* Turn off the virtual memory safety limit */
-       VM_BUFFERMEM,           /* struct: Set buffer memory thresholds */
-       VM_PAGECACHE,           /* struct: Set cache memory thresholds */
-       VM_PAGERDAEMON,         /* struct: Control kswapd behaviour */
-/*9*/  VM_PGT_CACHE            /* struct: Set page table cache parameters */
+       VM_SWAPCTL=1,           /* struct: Set vm swapping control */
+       VM_SWAPOUT=2,           /* int: Background pageout interval */
+       VM_FREEPG=3,            /* struct: Set free page thresholds */
+       VM_BDFLUSH=4,           /* struct: Control buffer cache flushing */
+       VM_OVERCOMMIT_MEMORY=5, /* Turn off the virtual memory safety limit */
+       VM_BUFFERMEM=6,         /* struct: Set buffer memory thresholds */
+       VM_PAGECACHE=7,         /* struct: Set cache memory thresholds */
+       VM_PAGERDAEMON=8,       /* struct: Control kswapd behaviour */
+       VM_PGT_CACHE=9          /* struct: Set page table cache parameters */
 };
 
 
 /* CTL_NET names: */
 enum
 {
-/*1*/  NET_CORE=1,
-       NET_ETHER,
-       NET_802,
-       NET_UNIX,
-       NET_IPV4,
-       NET_IPX,
-       NET_ATALK,
-       NET_NETROM,
-       NET_AX25,
-/*10*/ NET_BRIDGE,
-       NET_ROSE,
-       NET_IPV6,
-       NET_X25,
-       NET_TR,
-/*15*/ NET_DECNET
+       NET_CORE=1,
+       NET_ETHER=2,
+       NET_802=3,
+       NET_UNIX=4,
+       NET_IPV4=5,
+       NET_IPX=6,
+       NET_ATALK=7,
+       NET_NETROM=8,
+       NET_AX25=9,
+       NET_BRIDGE=10,
+       NET_ROSE=11,
+       NET_IPV6=12,
+       NET_X25=13,
+       NET_TR=14,
+       NET_DECNET=15
 };
 
 
 /* /proc/sys/net/core */
 enum
 {
-/*1*/  NET_CORE_WMEM_MAX=1,
-       NET_CORE_RMEM_MAX,
-       NET_CORE_WMEM_DEFAULT,
-       NET_CORE_RMEM_DEFAULT,
-       NET_CORE_MAX_BACKLOG,
-       NET_CORE_FASTROUTE,
-       NET_CORE_MSG_COST,
-       NET_CORE_MSG_BURST,
-/*10*/ NET_CORE_OPTMEM_MAX,
+       NET_CORE_WMEM_MAX=1,
+       NET_CORE_RMEM_MAX=2,
+       NET_CORE_WMEM_DEFAULT=3,
+       NET_CORE_RMEM_DEFAULT=4,
+/* was NET_CORE_DESTROY_DELAY */
+       NET_CORE_MAX_BACKLOG=6,
+       NET_CORE_FASTROUTE=7,
+       NET_CORE_MSG_COST=8,
+       NET_CORE_MSG_BURST=9,
+       NET_CORE_OPTMEM_MAX=10,
 };
 
 /* /proc/sys/net/ethernet */
@@ -147,143 +151,143 @@ enum
 
 enum
 {
-/*1*/  NET_UNIX_DESTROY_DELAY=1,
-/*2*/  NET_UNIX_DELETE_DELAY,
+       NET_UNIX_DESTROY_DELAY=1,
+       NET_UNIX_DELETE_DELAY=2,
 };
 
 /* /proc/sys/net/ipv4 */
 enum
 {
        /* v2.0 compatibile variables */
-/*8*/  NET_IPV4_FORWARD = 8,
-       NET_IPV4_DYNADDR = 9,
-
-/*16*/ NET_IPV4_CONF = 16,
-       NET_IPV4_NEIGH = 17,
-       NET_IPV4_ROUTE = 18,
-       NET_IPV4_FIB_HASH = 19,
-
-/*33*/ NET_IPV4_TCP_TIMESTAMPS=33,
-       NET_IPV4_TCP_WINDOW_SCALING,
-       NET_IPV4_TCP_SACK,
-       NET_IPV4_TCP_RETRANS_COLLAPSE,
-       NET_IPV4_DEFAULT_TTL,
-       NET_IPV4_AUTOCONFIG,
-       NET_IPV4_NO_PMTU_DISC,
-/*40*/ NET_IPV4_TCP_SYN_RETRIES,
-       NET_IPV4_IPFRAG_HIGH_THRESH,
-       NET_IPV4_IPFRAG_LOW_THRESH,
-       NET_IPV4_IPFRAG_TIME,
-       NET_IPV4_TCP_MAX_KA_PROBES,
-       NET_IPV4_TCP_KEEPALIVE_TIME,
-       NET_IPV4_TCP_KEEPALIVE_PROBES,
-       NET_IPV4_TCP_RETRIES1,
-       NET_IPV4_TCP_RETRIES2,
-       NET_IPV4_TCP_FIN_TIMEOUT,
-/*50*/ NET_IPV4_IP_MASQ_DEBUG,
-       NET_TCP_SYNCOOKIES,
-       NET_TCP_STDURG,
-       NET_TCP_RFC1337,
-       NET_TCP_SYN_TAILDROP,
-       NET_TCP_MAX_SYN_BACKLOG,
-       NET_IPV4_LOCAL_PORT_RANGE,
-       NET_IPV4_ICMP_ECHO_IGNORE_ALL,
-       NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
-       NET_IPV4_ICMP_SOURCEQUENCH_RATE,
-/*60*/ NET_IPV4_ICMP_DESTUNREACH_RATE,
-       NET_IPV4_ICMP_TIMEEXCEED_RATE,
-       NET_IPV4_ICMP_PARAMPROB_RATE,
-/*63*/ NET_IPV4_ICMP_ECHOREPLY_RATE,
+       NET_IPV4_FORWARD=8,
+       NET_IPV4_DYNADDR=9,
+
+       NET_IPV4_CONF=16,
+       NET_IPV4_NEIGH=17,
+       NET_IPV4_ROUTE=18,
+       NET_IPV4_FIB_HASH=19,
+
+       NET_IPV4_TCP_TIMESTAMPS=33,
+       NET_IPV4_TCP_WINDOW_SCALING=34,
+       NET_IPV4_TCP_SACK=35,
+       NET_IPV4_TCP_RETRANS_COLLAPSE=36,
+       NET_IPV4_DEFAULT_TTL=37,
+       NET_IPV4_AUTOCONFIG=38,
+       NET_IPV4_NO_PMTU_DISC=39,
+       NET_IPV4_TCP_SYN_RETRIES=40,
+       NET_IPV4_IPFRAG_HIGH_THRESH=41,
+       NET_IPV4_IPFRAG_LOW_THRESH=42,
+       NET_IPV4_IPFRAG_TIME=43,
+       NET_IPV4_TCP_MAX_KA_PROBES=44,
+       NET_IPV4_TCP_KEEPALIVE_TIME=45,
+       NET_IPV4_TCP_KEEPALIVE_PROBES=46,
+       NET_IPV4_TCP_RETRIES1=47,
+       NET_IPV4_TCP_RETRIES2=48,
+       NET_IPV4_TCP_FIN_TIMEOUT=49,
+       NET_IPV4_IP_MASQ_DEBUG=50,
+       NET_TCP_SYNCOOKIES=51,
+       NET_TCP_STDURG=52,
+       NET_TCP_RFC1337=53,
+       NET_TCP_SYN_TAILDROP=54,
+       NET_TCP_MAX_SYN_BACKLOG=55,
+       NET_IPV4_LOCAL_PORT_RANGE=56,
+       NET_IPV4_ICMP_ECHO_IGNORE_ALL=57,
+       NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS=58,
+       NET_IPV4_ICMP_SOURCEQUENCH_RATE=59,
+       NET_IPV4_ICMP_DESTUNREACH_RATE=60,
+       NET_IPV4_ICMP_TIMEEXCEED_RATE=61,
+       NET_IPV4_ICMP_PARAMPROB_RATE=62,
+       NET_IPV4_ICMP_ECHOREPLY_RATE=63,
 };
 
 enum {
-/*1*/  NET_IPV4_ROUTE_FLUSH = 1,
-       NET_IPV4_ROUTE_MIN_DELAY,
-       NET_IPV4_ROUTE_MAX_DELAY,
-       NET_IPV4_ROUTE_GC_THRESH,
-       NET_IPV4_ROUTE_MAX_SIZE,
-       NET_IPV4_ROUTE_GC_MIN_INTERVAL,
-       NET_IPV4_ROUTE_GC_TIMEOUT,
-       NET_IPV4_ROUTE_GC_INTERVAL,
-       NET_IPV4_ROUTE_REDIRECT_LOAD,
-/*10*/ NET_IPV4_ROUTE_REDIRECT_NUMBER,
-       NET_IPV4_ROUTE_REDIRECT_SILENCE,
-       NET_IPV4_ROUTE_ERROR_COST,
-       NET_IPV4_ROUTE_ERROR_BURST,
-/*14*/ NET_IPV4_ROUTE_GC_ELASTICITY,
+       NET_IPV4_ROUTE_FLUSH=1,
+       NET_IPV4_ROUTE_MIN_DELAY=2,
+       NET_IPV4_ROUTE_MAX_DELAY=3,
+       NET_IPV4_ROUTE_GC_THRESH=4,
+       NET_IPV4_ROUTE_MAX_SIZE=5,
+       NET_IPV4_ROUTE_GC_MIN_INTERVAL=6,
+       NET_IPV4_ROUTE_GC_TIMEOUT=7,
+       NET_IPV4_ROUTE_GC_INTERVAL=8,
+       NET_IPV4_ROUTE_REDIRECT_LOAD=9,
+       NET_IPV4_ROUTE_REDIRECT_NUMBER=10,
+       NET_IPV4_ROUTE_REDIRECT_SILENCE=11,
+       NET_IPV4_ROUTE_ERROR_COST=12,
+       NET_IPV4_ROUTE_ERROR_BURST=13,
+       NET_IPV4_ROUTE_GC_ELASTICITY=14,
 };
 
 enum
 {
-/*-2*/ NET_PROTO_CONF_ALL = -2,
-/*-3*/ NET_PROTO_CONF_DEFAULT = -3,
+       NET_PROTO_CONF_ALL=-2,
+       NET_PROTO_CONF_DEFAULT=-3,
 
        /* And device ifindices ... */
 };
 
 enum
 {
-/*1*/  NET_IPV4_CONF_FORWARDING = 1,
-       NET_IPV4_CONF_MC_FORWARDING,
-       NET_IPV4_CONF_PROXY_ARP,
-       NET_IPV4_CONF_ACCEPT_REDIRECTS,
-       NET_IPV4_CONF_SECURE_REDIRECTS,
-       NET_IPV4_CONF_SEND_REDIRECTS,
-       NET_IPV4_CONF_SHARED_MEDIA,
-       NET_IPV4_CONF_RP_FILTER,
-       NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
-/*10*/ NET_IPV4_CONF_BOOTP_RELAY,
-/*11*/ NET_IPV4_CONF_LOG_MARTIANS,
+       NET_IPV4_CONF_FORWARDING=1,
+       NET_IPV4_CONF_MC_FORWARDING=2,
+       NET_IPV4_CONF_PROXY_ARP=3,
+       NET_IPV4_CONF_ACCEPT_REDIRECTS=4,
+       NET_IPV4_CONF_SECURE_REDIRECTS=5,
+       NET_IPV4_CONF_SEND_REDIRECTS=6,
+       NET_IPV4_CONF_SHARED_MEDIA=7,
+       NET_IPV4_CONF_RP_FILTER=8,
+       NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
+       NET_IPV4_CONF_BOOTP_RELAY=10,
+       NET_IPV4_CONF_LOG_MARTIANS=11,
 };
 
 /* /proc/sys/net/ipv6 */
 enum {
-/*16*/ NET_IPV6_CONF = 16,
-       NET_IPV6_NEIGH = 17,
-/*18*/ NET_IPV6_ROUTE = 18,
+       NET_IPV6_CONF=16,
+       NET_IPV6_NEIGH=17,
+       NET_IPV6_ROUTE=18,
 };
 
 enum {
-/*1*/  NET_IPV6_ROUTE_FLUSH = 1,
-       NET_IPV6_ROUTE_GC_THRESH,
-       NET_IPV6_ROUTE_MAX_SIZE,
-       NET_IPV6_ROUTE_GC_MIN_INTERVAL,
-       NET_IPV6_ROUTE_GC_TIMEOUT,
-       NET_IPV6_ROUTE_GC_INTERVAL,
-/*7*/  NET_IPV6_ROUTE_GC_ELASTICITY,
+       NET_IPV6_ROUTE_FLUSH=1,
+       NET_IPV6_ROUTE_GC_THRESH=2,
+       NET_IPV6_ROUTE_MAX_SIZE=3,
+       NET_IPV6_ROUTE_GC_MIN_INTERVAL=4,
+       NET_IPV6_ROUTE_GC_TIMEOUT=5,
+       NET_IPV6_ROUTE_GC_INTERVAL=6,
+       NET_IPV6_ROUTE_GC_ELASTICITY=7,
 };
 
 enum {
-/*1*/  NET_IPV6_FORWARDING = 1,
-       NET_IPV6_HOP_LIMIT,
-       NET_IPV6_MTU,
-       NET_IPV6_ACCEPT_RA,
-       NET_IPV6_ACCEPT_REDIRECTS,
-       NET_IPV6_AUTOCONF,
-       NET_IPV6_DAD_TRANSMITS,
-       NET_IPV6_RTR_SOLICITS,
-       NET_IPV6_RTR_SOLICIT_INTERVAL,
-/*10*/ NET_IPV6_RTR_SOLICIT_DELAY,
+       NET_IPV6_FORWARDING=1,
+       NET_IPV6_HOP_LIMIT=2,
+       NET_IPV6_MTU=3,
+       NET_IPV6_ACCEPT_RA=4,
+       NET_IPV6_ACCEPT_REDIRECTS=5,
+       NET_IPV6_AUTOCONF=6,
+       NET_IPV6_DAD_TRANSMITS=7,
+       NET_IPV6_RTR_SOLICITS=8,
+       NET_IPV6_RTR_SOLICIT_INTERVAL=9,
+       NET_IPV6_RTR_SOLICIT_DELAY=10,
 };
 
 /* /proc/sys/net/<protocol>/neigh/<dev> */
 enum {
-/*1*/  NET_NEIGH_MCAST_SOLICIT=1,
-       NET_NEIGH_UCAST_SOLICIT,
-       NET_NEIGH_APP_SOLICIT,
-       NET_NEIGH_RETRANS_TIME,
-       NET_NEIGH_REACHABLE_TIME,
-       NET_NEIGH_DELAY_PROBE_TIME,
-       NET_NEIGH_GC_STALE_TIME,
-       NET_NEIGH_UNRES_QLEN,
-       NET_NEIGH_PROXY_QLEN,
-/*10*/ NET_NEIGH_ANYCAST_DELAY,
-       NET_NEIGH_PROXY_DELAY,
-       NET_NEIGH_LOCKTIME,
-       NET_NEIGH_GC_INTERVAL,
-       NET_NEIGH_GC_THRESH1,
-       NET_NEIGH_GC_THRESH2,
-/*16*/ NET_NEIGH_GC_THRESH3
+       NET_NEIGH_MCAST_SOLICIT=1,
+       NET_NEIGH_UCAST_SOLICIT=2,
+       NET_NEIGH_APP_SOLICIT=3,
+       NET_NEIGH_RETRANS_TIME=4,
+       NET_NEIGH_REACHABLE_TIME=5,
+       NET_NEIGH_DELAY_PROBE_TIME=6,
+       NET_NEIGH_GC_STALE_TIME=7,
+       NET_NEIGH_UNRES_QLEN=8,
+       NET_NEIGH_PROXY_QLEN=9,
+       NET_NEIGH_ANYCAST_DELAY=10,
+       NET_NEIGH_PROXY_DELAY=11,
+       NET_NEIGH_LOCKTIME=12,
+       NET_NEIGH_GC_INTERVAL=13,
+       NET_NEIGH_GC_THRESH1=14,
+       NET_NEIGH_GC_THRESH2=15,
+       NET_NEIGH_GC_THRESH3=16
 };
 
 /* /proc/sys/net/ipx */
@@ -291,83 +295,83 @@ enum {
 
 /* /proc/sys/net/appletalk */
 enum {
-/*1*/  NET_ATALK_AARP_EXPIRY_TIME = 1,
-       NET_ATALK_AARP_TICK_TIME,
-       NET_ATALK_AARP_RETRANSMIT_LIMIT,
-/*4*/  NET_ATALK_AARP_RESOLVE_TIME,
+       NET_ATALK_AARP_EXPIRY_TIME=1,
+       NET_ATALK_AARP_TICK_TIME=2,
+       NET_ATALK_AARP_RETRANSMIT_LIMIT=3,
+       NET_ATALK_AARP_RESOLVE_TIME=4,
 };
 
 
 /* /proc/sys/net/netrom */
 enum {
-/*1*/  NET_NETROM_DEFAULT_PATH_QUALITY = 1,
-       NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER,
-       NET_NETROM_NETWORK_TTL_INITIALISER,
-       NET_NETROM_TRANSPORT_TIMEOUT,
-       NET_NETROM_TRANSPORT_MAXIMUM_TRIES,
-       NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY,
-       NET_NETROM_TRANSPORT_BUSY_DELAY,
-       NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE,
-       NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT,
-/*10*/ NET_NETROM_ROUTING_CONTROL,
-/*11*/ NET_NETROM_LINK_FAILS_COUNT
+       NET_NETROM_DEFAULT_PATH_QUALITY=1,
+       NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER=2,
+       NET_NETROM_NETWORK_TTL_INITIALISER=3,
+       NET_NETROM_TRANSPORT_TIMEOUT=4,
+       NET_NETROM_TRANSPORT_MAXIMUM_TRIES=5,
+       NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY=6,
+       NET_NETROM_TRANSPORT_BUSY_DELAY=7,
+       NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8,
+       NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9,
+       NET_NETROM_ROUTING_CONTROL=10,
+       NET_NETROM_LINK_FAILS_COUNT=11
 };
 
 /* /proc/sys/net/ax25 */
 enum {
-/*1*/  NET_AX25_IP_DEFAULT_MODE = 1,
-       NET_AX25_DEFAULT_MODE,
-       NET_AX25_BACKOFF_TYPE,
-       NET_AX25_CONNECT_MODE,
-       NET_AX25_STANDARD_WINDOW,
-       NET_AX25_EXTENDED_WINDOW,
-       NET_AX25_T1_TIMEOUT,
-       NET_AX25_T2_TIMEOUT,
-       NET_AX25_T3_TIMEOUT,
-/*10*/ NET_AX25_IDLE_TIMEOUT,
-       NET_AX25_N2,
-       NET_AX25_PACLEN,
-       NET_AX25_PROTOCOL,
-/*14*/ NET_AX25_DAMA_SLAVE_TIMEOUT
+       NET_AX25_IP_DEFAULT_MODE=1,
+       NET_AX25_DEFAULT_MODE=2,
+       NET_AX25_BACKOFF_TYPE=3,
+       NET_AX25_CONNECT_MODE=4,
+       NET_AX25_STANDARD_WINDOW=5,
+       NET_AX25_EXTENDED_WINDOW=6,
+       NET_AX25_T1_TIMEOUT=7,
+       NET_AX25_T2_TIMEOUT=8,
+       NET_AX25_T3_TIMEOUT=9,
+       NET_AX25_IDLE_TIMEOUT=10,
+       NET_AX25_N2=11,
+       NET_AX25_PACLEN=12,
+       NET_AX25_PROTOCOL=13,
+       NET_AX25_DAMA_SLAVE_TIMEOUT=14
 };
 
 /* /proc/sys/net/rose */
 enum {
-/*1*/  NET_ROSE_RESTART_REQUEST_TIMEOUT = 1,
-       NET_ROSE_CALL_REQUEST_TIMEOUT,
-       NET_ROSE_RESET_REQUEST_TIMEOUT,
-       NET_ROSE_CLEAR_REQUEST_TIMEOUT,
-       NET_ROSE_ACK_HOLD_BACK_TIMEOUT,
-       NET_ROSE_ROUTING_CONTROL,
-       NET_ROSE_LINK_FAIL_TIMEOUT,
-       NET_ROSE_MAX_VCS,
-       NET_ROSE_WINDOW_SIZE,
-/*10*/ NET_ROSE_NO_ACTIVITY_TIMEOUT,
+       NET_ROSE_RESTART_REQUEST_TIMEOUT=1,
+       NET_ROSE_CALL_REQUEST_TIMEOUT=2,
+       NET_ROSE_RESET_REQUEST_TIMEOUT=3,
+       NET_ROSE_CLEAR_REQUEST_TIMEOUT=4,
+       NET_ROSE_ACK_HOLD_BACK_TIMEOUT=5,
+       NET_ROSE_ROUTING_CONTROL=6,
+       NET_ROSE_LINK_FAIL_TIMEOUT=7,
+       NET_ROSE_MAX_VCS=8,
+       NET_ROSE_WINDOW_SIZE=9,
+       NET_ROSE_NO_ACTIVITY_TIMEOUT=10,
 };
 
 /* /proc/sys/net/x25 */
 enum {
-/*1*/  NET_X25_RESTART_REQUEST_TIMEOUT = 1,
-       NET_X25_CALL_REQUEST_TIMEOUT,
-       NET_X25_RESET_REQUEST_TIMEOUT,
-       NET_X25_CLEAR_REQUEST_TIMEOUT,
-/*5*/  NET_X25_ACK_HOLD_BACK_TIMEOUT
+       NET_X25_RESTART_REQUEST_TIMEOUT=1,
+       NET_X25_CALL_REQUEST_TIMEOUT=2,
+       NET_X25_RESET_REQUEST_TIMEOUT=3,
+       NET_X25_CLEAR_REQUEST_TIMEOUT=4,
+       NET_X25_ACK_HOLD_BACK_TIMEOUT=5
 };
 
 /* /proc/sys/net/token-ring */
 enum
 {
-/*1*/  NET_TR_RIF_TIMEOUT=1
+       NET_TR_RIF_TIMEOUT=1
 };
 
 /* /proc/sys/net/decnet */
 enum {
-/*1*/  NET_DECNET_DEF_T3_BROADCAST = 1,
-       NET_DECNET_DEF_T3_POINTTOPOINT,
-       NET_DECNET_DEF_T1,
-       NET_DECNET_DEF_BCT1,
-       NET_DECNET_CACHETIMEOUT,
-/*6*/  NET_DECNET_DEBUG_LEVEL
+       NET_DECNET_DEF_T3_BROADCAST=1,
+       NET_DECNET_DEF_T3_POINTTOPOINT=2,
+       NET_DECNET_DEF_T1=3,
+       NET_DECNET_DEF_BCT1=4,
+       NET_DECNET_CACHETIMEOUT=5,
+       NET_DECNET_DEBUG_LEVEL=6
 };
 
 /* CTL_PROC names: */
@@ -375,29 +379,29 @@ enum {
 /* CTL_FS names: */
 enum
 {
-/*1*/  FS_NRINODE=1,           /* int: current number of allocated inodes */
-       FS_STATINODE,
-       FS_MAXINODE,            /* int: maximum number of inodes that can be allocated */
-       FS_NRDQUOT,             /* int: current number of allocated dquots */
-       FS_MAXDQUOT,            /* int: maximum number of dquots that can be allocated */
-       FS_NRFILE,              /* int: current number of allocated filedescriptors */
-       FS_MAXFILE,             /* int: maximum number of filedescriptors that can be allocated */
-       FS_DENTRY,
-       FS_NRSUPER,             /* int: current number of allocated super_blocks */
-/*10*/ FS_MAXSUPER,            /* int: maximum number of super_blocks that can be allocated */
+       FS_NRINODE=1,   /* int:current number of allocated inodes */
+       FS_STATINODE=2,
+       FS_MAXINODE=3,  /* int:maximum number of inodes that can be allocated */
+       FS_NRDQUOT=4,   /* int:current number of allocated dquots */
+       FS_MAXDQUOT=5,  /* int:maximum number of dquots that can be allocated */
+       FS_NRFILE=6,    /* int:current number of allocated filedescriptors */
+       FS_MAXFILE=7,   /* int:maximum number of filedescriptors that can be allocated */
+       FS_DENTRY=8,
+       FS_NRSUPER=9,   /* int:current number of allocated super_blocks */
+       FS_MAXSUPER=10, /* int:maximum number of super_blocks that can be allocated */
 };
 
 /* CTL_DEBUG names: */
 
 /* CTL_DEV names: */
 enum {
-/*1*/  DEV_CDROM = 1,
-/*2*/  DEV_HWMON,
+       DEV_CDROM=1,
+       DEV_HWMON=2,
 };
 
 /* /proc/sys/dev/cdrom */
 enum {
-/*1*/  DEV_CDROM_INFO = 1,
+       DEV_CDROM_INFO=1,
 };
 
 #ifdef __KERNEL__
index b07dddb167595decc83ed0d2c413bb62cf2eab4c..d2b68111f5573003d314c74fbe4165820a5e3c4b 100644 (file)
@@ -428,8 +428,8 @@ typedef __u32 zorro_id;
 #define  ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE      ZORRO_ID(M_TECH_GERMANY, 0x24, 0)
 
 #define ZORRO_MANUF_GREAT_VALLEY_PRODUCTS_4                    0x0891
-#define  ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG                 ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x01, 0)
-#define  ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM                 ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x02, 0)
+#define  ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM                 ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x01, 0)
+#define  ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG                 ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x02, 0)
 
 #define ZORRO_MANUF_APOLLO_1                                   0x0892
 #define  ZORRO_PROD_APOLLO_A1200                               ZORRO_ID(APOLLO_1, 0x01, 0)
index df0873fde35eebca198198ff178250e28bb161a0..4adf92e9d536b80f7440001e0a7ee7daa0186075 100644 (file)
@@ -377,7 +377,7 @@ char *get_options(char *str, int *ints)
        int i=1;
 
        while (cur && isdigit(*cur) && i <= 10) {
-               ints[i++] = simple_strtoul(cur,NULL,0);
+               ints[i++] = simple_strtol(cur,NULL,0);
                if ((cur = strchr(cur,',')) != NULL)
                        cur++;
        }
index 17669321832226dadb748d0b236fc9677888c027..ed0353184a530f4576790ac6a33fe6e6b3098e27 100644 (file)
  *
  *  Now we silently close acct_file on attempt to reopen. Cleaned sys_acct().
  *  XTerms and EMACS are manifestations of pure evil. 21/10/98, AV.
+ *
+ *  Fixed a nasty interaction with with sys_umount(). If the accointing
+ *  was suspeneded we failed to stop it on umount(). Messy.
+ *  Another one: remount to readonly didn't stop accounting.
+ *     Question: what should we do if we have CAP_SYS_ADMIN but not
+ *  CAP_SYS_PACCT? Current code does the following: umount returns -EBUSY
+ *  unless we are messing with the root. In that case we are getting a
+ *  real mess with do_remount_sb(). 9/11/98, AV.
+ *
+ *  Fixed a bunch of races (and pair of leaks). Probably not the best way,
+ *  but this one obviously doesn't introduce deadlocks. Later. BTW, found
+ *  one race (and leak) in BSD implementation.
+ *  OK, that's better. ANOTHER race and leak in BSD variant. There always
+ *  is one more bug... TODO: move filp_open into open.c and make
+ *  parameters sysctl-controllable. 10/11/98, AV.
  */
 
 #include <linux/config.h>
  * These constants control the amount of freespace that suspend and
  * resume the process accounting system, and the time delay between
  * each check.
+ * Turned into sysctl-controllable parameters. AV, 12/11/98
  */
 
-#define RESUME         (4)       /* More than 4% free space will resume */
-#define SUSPEND                (2)       /* Less than 2% free space will suspend */
-#define ACCT_TIMEOUT   (30 * HZ) /* 30 second timeout between checks */
+int acct_parm[3] = {4, 2, 30};
+#define RESUME         (acct_parm[0])  /* >foo% free space - resume */
+#define SUSPEND                (acct_parm[1])  /* <foo% free space - suspend */
+#define ACCT_TIMEOUT   (acct_parm[2])  /* foo second timeout between checks */
 
 /*
  * External references and all of the globals.
@@ -66,6 +83,7 @@ static volatile int acct_active = 0;
 static volatile int acct_needcheck = 0;
 static struct file *acct_file = NULL;
 static struct timer_list acct_timer = { NULL, NULL, 0, 0, acct_timeout };
+static int do_acct_process(long, struct file *);
 
 /*
  * Called whenever the timer says to check the free space.
@@ -78,39 +96,58 @@ void acct_timeout(unsigned long unused)
 /*
  * Check the amount of free space and suspend/resume accordingly.
  */
-static void check_free_space(void)
+static int check_free_space(struct file *file)
 {
        mm_segment_t fs;
        struct statfs sbuf;
        struct super_block *sb;
+       int res = acct_active;
+       int act;
 
-       if (!acct_file || !acct_needcheck)
-               return;
+       if (!file || !acct_needcheck)
+               return res;
 
-       sb = acct_file->f_dentry->d_inode->i_sb;
+       sb = file->f_dentry->d_inode->i_sb;
        if (!sb->s_op || !sb->s_op->statfs)
-               return;
+               return res;
 
        fs = get_fs();
        set_fs(KERNEL_DS);
+       /* May block */
        sb->s_op->statfs(sb, &sbuf, sizeof(struct statfs));
        set_fs(fs);
 
+       if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100)
+               act = -1;
+       else if (sbuf.f_bavail >= RESUME * sbuf.f_blocks / 100)
+               act = 1;
+       else
+               act = 0;
+
+       /*
+        * If some joker switched acct_file under us we'ld better be
+        * silent and _not_ touch anything.
+        */
+       if (file != acct_file)
+               return act ? (act>0) : res;
+
        if (acct_active) {
-               if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100) {
+               if (act < 0) {
                        acct_active = 0;
                        printk(KERN_INFO "Process accounting paused\r\n");
                }
        } else {
-               if (sbuf.f_bavail >= RESUME * sbuf.f_blocks / 100) {
+               if (act > 0) {
                        acct_active = 1;
                        printk(KERN_INFO "Process accounting resumed\r\n");
                }
        }
+
        del_timer(&acct_timer);
        acct_needcheck = 0;
-       acct_timer.expires = jiffies + ACCT_TIMEOUT;
+       acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ;
        add_timer(&acct_timer);
+       return acct_active;
 }
 
 /*
@@ -121,9 +158,7 @@ static void check_free_space(void)
  */
 asmlinkage int sys_acct(const char *name)
 {
-       struct dentry *dentry;
-       struct inode *inode;
-       struct file_operations *ops;
+       struct file *file = NULL, *old_acct = NULL;
        char *tmp;
        int error = -EPERM;
 
@@ -131,82 +166,57 @@ asmlinkage int sys_acct(const char *name)
        if (!capable(CAP_SYS_PACCT))
                goto out;
 
+       if (name) {
+               tmp = getname(name);
+               error = PTR_ERR(tmp);
+               if (IS_ERR(tmp))
+                       goto out;
+               /* Difference from BSD - they don't do O_APPEND */
+               file = filp_open(tmp, O_WRONLY|O_APPEND, 0);
+               putname(tmp);
+               if (IS_ERR(file)) {
+                       error = PTR_ERR(file);
+                       goto out;
+               }
+               error = -EACCES;
+               if (!S_ISREG(file->f_dentry->d_inode->i_mode)) 
+                       goto out_err;
+
+               error = -EIO;
+               if (!file->f_op->write) 
+                       goto out_err;
+       }
+
+       error = 0;
        if (acct_file) {
-               /* fput() may block, so just in case... */
-               struct file *tmp = acct_file;
-               if (acct_active)
-                       acct_process(0); 
+               old_acct = acct_file;
                del_timer(&acct_timer);
                acct_active = 0;
                acct_needcheck = 0;
                acct_file = NULL;
-               fput(tmp);
        }
-       error = 0;
-       if (!name)              /* We are done */
-               goto out;
-
-       tmp = getname(name);
-       error = PTR_ERR(tmp);
-       if (IS_ERR(tmp))
-               goto out;
-
-       dentry = open_namei(tmp, O_RDWR, 0600);
-       putname(tmp);
-
-       error = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
-               goto out;
-
-       inode = dentry->d_inode;
-
-       error = -EACCES;
-       if (!S_ISREG(inode->i_mode)) 
-               goto out_d;
-
-       error = -EIO;
-       if (!inode->i_op || !(ops = inode->i_op->default_file_ops) || 
-           !ops->write) 
-               goto out_d;
-
-       error = -EUSERS;
-       if (!(acct_file = get_empty_filp()))
-               goto out_d;
-
-       acct_file->f_mode = (O_WRONLY + 1) & O_ACCMODE;
-       acct_file->f_flags = O_WRONLY;
-       acct_file->f_dentry = dentry;
-       acct_file->f_pos = inode->i_size;
-       acct_file->f_reada = 0;
-       acct_file->f_op = ops;
-       error = get_write_access(inode);
-       if (error)
-               goto out_f;
-       if (ops->open)
-               error = ops->open(inode, acct_file);
-       if (error) {
-               put_write_access(inode);
-               goto out_f;
+       if (name) {
+               acct_file = file;
+               acct_needcheck = 0;
+               acct_active = 1;
+               acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ;
+               add_timer(&acct_timer);
+       }
+       if (old_acct) {
+               do_acct_process(0,old_acct);
+               fput(old_acct);
        }
-       acct_needcheck = 0;
-       acct_active = 1;
-       acct_timer.expires = jiffies + ACCT_TIMEOUT;
-       add_timer(&acct_timer);
-       goto out;
-out_f:
-       /* decrementing f_count is _not_ enough */
-       put_filp(acct_file);
-       acct_file = NULL;
-out_d:
-       dput(dentry);
 out:
        unlock_kernel();
        return error;
+out_err:
+       fput(file);
+       goto out;
 }
 
 void acct_auto_close(kdev_t dev)
 {
-       if (acct_active && acct_file && acct_file->f_dentry->d_inode->i_dev == dev)
+       if (acct_file && acct_file->f_dentry->d_inode->i_dev == dev)
                sys_acct((char *)NULL);
 }
 
@@ -260,7 +270,10 @@ static comp_t encode_comp_t(unsigned long value)
 #define KSTK_EIP(stack) (((unsigned long *)(stack))[1019])
 #define KSTK_ESP(stack) (((unsigned long *)(stack))[1022])
 
-int acct_process(long exitcode)
+/*
+ *  do_acct_process does all actual work.
+ */
+static int do_acct_process(long exitcode, struct file *file)
 {
        struct acct ac;
        mm_segment_t fs;
@@ -268,14 +281,15 @@ int acct_process(long exitcode)
 
        /*
         * First check to see if there is enough free_space to continue
-        * the process accounting system. Check_free_space toggles the
-        * acct_active flag so we need to check that after check_free_space.
+        * the process accounting system.
         */
-       check_free_space();
-
-       if (!acct_active)
+       if (!file)
                return 0;
-
+       file->f_count++;
+       if (!check_free_space(file)) {
+               fput(file);
+               return 0;
+       }
 
        /*
         * Fill the accounting struct with the needed info as recorded
@@ -327,12 +341,21 @@ int acct_process(long exitcode)
          */
        fs = get_fs();
        set_fs(KERNEL_DS);
-       acct_file->f_op->write(acct_file, (char *)&ac,
-                              sizeof(struct acct), &acct_file->f_pos);
+       file->f_op->write(file, (char *)&ac,
+                              sizeof(struct acct), &file->f_pos);
        set_fs(fs);
+       fput(file);
        return 0;
 }
 
+/*
+ * acct_process - now just a wrapper around do_acct_process
+ */
+int acct_process(long exitcode)
+{
+       return do_acct_process(exitcode, acct_file);
+}
+
 #else
 /*
  * Dummy system call when BSD process accounting is not configured
index 6ef166a146c554e8243fd4b34378f84e24df90c8..f439d77db3878c8b42ae8a0cb6b9703d84c1d268 100644 (file)
@@ -58,6 +58,10 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
                  void *buffer, size_t *lenp);
 #endif
 
+#ifdef CONFIG_BSD_PROCESS_ACCT
+extern int acct_parm[];
+#endif
+
 extern int pgt_cache_water[];
 
 static int parse_table(int *, int, void *, size_t *, void *, size_t,
@@ -192,6 +196,10 @@ static ctl_table kern_table[] = {
 #ifdef CONFIG_CHR_DEV_SG
        {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int),
         0444, NULL, &proc_dointvec},
+#endif
+#ifdef CONFIG_BSD_PROCESS_ACCT
+       {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
+       0644, NULL, &proc_dointvec},
 #endif
        {0}
 };
index b2e72d58440ff2aa3ac1d2ca49cf15f72b613475..4318bc58656a7f61235bcb23a1f17d507662aa3c 100644 (file)
@@ -39,6 +39,13 @@ unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
        return result;
 }
 
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+       if(*cp=='-')
+               return -simple_strtoul(cp+1,endp,base);
+       return simple_strtoul(cp,endp,base);
+}
+
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)    ((c) >= '0' && (c) <= '9')
 
index 1a0903a6e144b9f1b73410e868c37dc6232d5556..1691cc68c71a909756207eec6a863d4ffe3ddfc9 100644 (file)
@@ -1523,9 +1523,8 @@ generic_file_write(struct file *file, const char *buf,
        unsigned long   limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
        struct page     *page, **hash;
        unsigned long   page_cache = 0;
-       unsigned long   pgpos, offset;
-       unsigned long   bytes, written;
-       long            status, sync, didread;
+       unsigned long   written;
+       long            status, sync;
 
        if (!inode->i_op || !inode->i_op->updatepage)
                return -EIO;
@@ -1556,14 +1555,15 @@ generic_file_write(struct file *file, const char *buf,
        }
 
        while (count) {
+               unsigned long bytes, pgpos, offset;
                /*
                 * Try to find the page in the cache. If it isn't there,
                 * allocate a free page.
                 */
                offset = (pos & ~PAGE_MASK);
                pgpos = pos & PAGE_MASK;
-
-               if ((bytes = PAGE_SIZE - offset) > count)
+               bytes = PAGE_SIZE - offset;
+               if (bytes > count)
                        bytes = count;
 
                hash = page_hash(inode, pgpos);
@@ -1580,50 +1580,20 @@ generic_file_write(struct file *file, const char *buf,
                        page_cache = 0;
                }
 
-               /*
-                * Note: setting of the PG_locked bit is handled
-                * below the i_op->xxx interface.
-                */
-               didread = 0;
-page_wait:
                wait_on_page(page);
-               if (PageUptodate(page))
-                       goto do_update_page;
+               set_bit(PG_locked, &page->flags);
 
-               /*
-                * The page is not up-to-date ... if we're writing less
-                * than a full page of data, we may have to read it first.
-                * But if the page is past the current end of file, we must
-                * clear it before updating.
-                */
-               if (bytes < PAGE_SIZE) {
-                       if (pgpos < inode->i_size) {
-                               status = -EIO;
-                               if (didread >= 2)
-                                       goto done_with_page;
-                               status = inode->i_op->readpage(file, page);
-                               if (status < 0)
-                                       goto done_with_page;
-                               didread++;
-                               goto page_wait;
-                       } else {
-                               /* Must clear for partial writes */
-                               memset((void *) page_address(page), 0,
-                                        PAGE_SIZE);
-                       }
+               bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
+               if (!bytes) {
+                       status = -EFAULT;
+                       clear_bit(PG_locked, &page->flags);
+                       wake_up(&page->wait);
+                       __free_page(page);
+                       break;
                }
-               /*
-                * N.B. We should defer setting PG_uptodate at least until
-                * the data is copied. A failure in i_op->updatepage() could
-                * leave the page with garbage data.
-                */
-               set_bit(PG_uptodate, &page->flags);
 
-do_update_page:
-               /* All right, the page is there.  Now update it. */
-               status = inode->i_op->updatepage(file, page, buf,
-                                                       offset, bytes, sync);
-done_with_page:
+               status = inode->i_op->updatepage(file, page, offset, bytes, sync);
+
                __free_page(page);
                if (status < 0)
                        break;
index 10b9918913bb747ba5028d95f4f5af04762d290f..32fc3d9a85436a42bc7f64c8ae55ec0d799b3b89 100644 (file)
@@ -538,6 +538,8 @@ int kswapd(void *unused)
                do {
                        if (!do_try_to_free_page(0))
                                break;
+                       if (nr_free_pages > 2*freepages.high)
+                               break;
                } while (time_before_eq(jiffies,end_time));
        }
        /* As if we could ever get here - maybe we want to make this killable */
index 1c9f7e76549fc985dec09296b380878ad36980f3..f544da731087aa6dc18f8b6d5bd1627192f85c8b 100644 (file)
@@ -98,18 +98,20 @@ int fddi_rebuild_header(struct sk_buff      *skb)
 {
        struct fddihdr *fddi = (struct fddihdr *)skb->data;
 
-       if (fddi->hdr.llc_snap.ethertype != __constant_htons(ETH_P_IP))
+#ifdef CONFIG_INET
+       if (fddi->hdr.llc_snap.ethertype == __constant_htons(ETH_P_IP))
+               /* Try to get ARP to resolve the header and fill destination address */
+               return arp_find(fddi->daddr, skb);
+       else
+#endif 
        {
                printk("%s: Don't know how to resolve type %02X addresses.\n",
                       skb->dev->name, htons(fddi->hdr.llc_snap.ethertype));
                return(0);
        }
-
-       /* Try to get ARP to resolve the header and fill destination address */
-
-       return arp_find(fddi->daddr, skb);
 }
 
+
 /*
  * Determine the packet's protocol ID and fill in skb fields.
  * This routine is called before an incoming packet is passed
index 92bdc4c97f013398d6d1face46ab8f7fc33cd0b6..01861d8e4cb82f6721d0474caf61eee23b136acb 100644 (file)
@@ -330,8 +330,6 @@ static int econet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
        {
                /* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
-               unsigned char *p;
-
                dev_lock_list();
                
                skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, 
index 118a7276bdc5ecb644461b01287bbc68a607b72e..ba7fe087376d03d83f24d35d0f125e54e8254fec 100644 (file)
@@ -93,7 +93,7 @@
 #include <net/sock.h>
 #include <net/scm.h>
 
-
+static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
 static long long sock_lseek(struct file *file, long long offset, int whence);
 static ssize_t sock_read(struct file *file, char *buf,
                         size_t size, loff_t *ppos);
@@ -121,7 +121,7 @@ static struct file_operations socket_file_ops = {
        sock_poll,
        sock_ioctl,
        NULL,                   /* mmap */
-       NULL,                   /* no special open code... */
+       sock_no_open,           /* special open code to disallow open via /proc */
        NULL,                   /* flush */
        sock_close,
        NULL,                   /* no fsync */
@@ -305,6 +305,17 @@ struct socket *sock_alloc(void)
        return sock;
 }
 
+/*
+ *     In theory you can't get an open on this inode, but /proc provides
+ *     a back door. Remember to keep it shut otherwise you'll let the
+ *     creepy crawlies in.
+ */
+  
+static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
+{
+       return -ENXIO;
+}
+
 void sock_release(struct socket *sock)
 {
        if (sock->state != SS_UNCONNECTED)
index f92f87e1f45a8fb165fde0e1daefd3c13b70c679..678098884a29552173e2dbd3dc5182cc3765cd46 100644 (file)
@@ -56,6 +56,8 @@ typedef struct wan_stat_entry
 
 /****** Function Prototypes *************************************************/
 
+#ifdef CONFIG_PROC_FS
+
 /* Proc filesystem interface */
 static int router_proc_perms(struct inode *, int);
 static ssize_t router_proc_read(struct file* file, char* buf, size_t count,                                    loff_t *ppos);
@@ -176,7 +178,7 @@ static struct inode_operations wandev_inode =
 /*
  *     /proc/net/router 
  */
+
 static struct proc_dir_entry proc_router =
 {
        0,                      /* .low_ino */
@@ -528,3 +530,30 @@ static int wandev_get_info(char* buf, char** start, off_t offs, int len,
  *     End
  */
  
+#else
+
+/*
+ *     No /proc - output stubs
+ */
+__initfunc(int wanrouter_proc_init(void))
+{
+       return 0;
+}
+
+void wanrouter_proc_cleanup(void)
+{
+       return;
+}
+
+int wanrouter_proc_add(wan_device_t *wandev)
+{
+       return 0;
+}
+
+int wanrouter_proc_delete(wan_device_t *wandev)
+{
+       return 0;
+}
+
+#endif
index c7c2fdc26195c64d3f71edf78c2d1dd6cae00650..d6170ec46d4cafb69d2c856c505ebc66a341c4f4 100644 (file)
@@ -62,9 +62,6 @@ print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey
 {
     int j;
     char menu_item[menu_width+1];
-#if OLD_NCURSES
-     int i;
-#endif
 
     strncpy(menu_item, item, menu_width);
     menu_item[menu_width] = 0;
@@ -74,8 +71,11 @@ print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey
     wattrset (win, menubox_attr);
     wmove (win, choice, 0);
 #if OLD_NCURSES
-    for (i = 0; i < menu_width; i++)
-       waddch (win, ' ');
+    {
+        int i;
+        for (i = 0; i < menu_width; i++)
+           waddch (win, ' ');
+    }
 #else
     wclrtoeol(win);
 #endif
index 848e82e70d64d13d138e1b1b1d49de0d780232f9..415a42f87fcbd2dcdb020e26c7c962b28db3367e 100644 (file)
@@ -453,9 +453,6 @@ print_line (WINDOW * win, int row, int width)
 {
     int y, x;
     char *line;
-#if OLD_NCURSES
-     int i;
-#endif
 
     line = get_line ();
     line += MIN (strlen (line), hscroll);      /* Scroll horizontally */
@@ -466,8 +463,11 @@ print_line (WINDOW * win, int row, int width)
     getyx (win, y, x);
     /* Clear 'residue' of previous line */
 #if OLD_NCURSES
-    for (i = 0; i < width - x; i++)
-       waddch (win, ' ');
+    {
+        int i;
+        for (i = 0; i < width - x; i++)
+           waddch (win, ' ');
+    }
 #else
     wclrtoeol(win);
 #endif