Import 2.1.102.1.10
authorLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:39 +0000 (23 15:12 -0500)
committerLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:39 +0000 (23 15:12 -0500)
85 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/devices.tex
Documentation/devices.txt
Makefile
arch/alpha/defconfig
arch/alpha/lib/strlen_user.S
arch/i386/boot/Makefile
arch/i386/kernel/ksyms.c
drivers/block/floppy.c
drivers/block/ide-cd.c
drivers/cdrom/Makefile
drivers/cdrom/cdrom.c
drivers/cdrom/mcd.c
drivers/char/ChangeLog
drivers/char/serial.c
drivers/isdn/teles/proto.h[new file with mode: 0644]
drivers/net/tulip.c
drivers/scsi/Config.in
drivers/scsi/Makefile
drivers/scsi/advansys.c
drivers/scsi/scsi.c
drivers/scsi/scsi.h
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/scsi/sr.h
drivers/scsi/sr_ioctl.c
drivers/scsi/sr_vendor.c[new file with mode: 0644]
fs/binfmt_elf.c
fs/buffer.c
fs/exec.c
fs/ext2/balloc.c
fs/ext2/dir.c
fs/ext2/fsync.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext2/truncate.c
include/asm-alpha/bitops.h
include/asm-alpha/byteorder.h
include/asm-alpha/uaccess.h
include/asm-i386/bitops.h
include/asm-i386/byteorder.h
include/asm-i386/uaccess.h
include/linux/fs.h
include/linux/in.h
include/linux/skbuff.h
include/linux/socket.h
include/net/ip.h
include/net/ipv6.h
include/net/tcp.h
net/appletalk/ddp.c
net/bridge/br.c
net/core/datagram.c
net/core/dev.c
net/core/iovec.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/icmp.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipmr.c
net/ipv4/packet.c
net/ipv4/rarp.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/icmp.c
net/ipv6/ipv6_output.c
net/ipv6/ipv6_sockglue.c
net/ipv6/raw.c
net/ipv6/udp.c
net/ipx/af_ipx.c
net/netlink.c
net/socket.c
net/unix/af_unix.c

index dd104d0..44992a6 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -713,6+713,10 @@ S: 2a, rue de l'Acier
 S: L-4505 Differdange
 S: Luxembourg
 
+N: Gerd Knorr
+E: kraxel@cs.tu-berlin.de
+D: SCSI CD-ROM driver hacking, minor bug fixes
+
 N: Harald Koenig
 E: koenig@tat.physik.uni-tuebingen.de
 D: XFree86 (S3), DCF77, some kernel hacks and fixes
dissimilarity index 90%
index 9ccdff9..ca3520d 100644 (file)
-Intro
-=====
-
-This document contains a list of the latest stable releases of the most
-important packages for Linux as well as instructions for newcomers to
-the 2.0.x series of kernels.  By glancing through it, you should be
-able to find out what you need to upgrade in order to successfully run
-the latest kernels.
-
-   It was originally based on material from the linux-kernel mailing
-list, Jared Mauch's web page "Software Victims of the 1.3 Kernel
-Development" (http://www2.nether.net/~jared/victim.html), and Axel
-Boldt's (boldt@math.ucsb.edu) Configure.help file, among other sources,
-and was originally written and maintained by Alessandro Sigala
-(ssigala@globalnet.it).
-
-   There is now a web page based on this material, thanks to John
-Taylor.  Check out http://www.cviog.uga.edu/LinuxBleed.html if you
-prefer a HTML-ized shopping list.
-
-   Para aquellos que prefieran una version en castellano de este
-documento, consultad la traduccion de Alfredo Sanjuan en
-http://slug.ctv.es/~alfredo/Cambios.html (Spanish translation).
-
-   Akik magyarul szeretnenek olvasni az uj kernellel kapcsolatos
-valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
-http://www.datanet.hu/generations/linux/newkernel.html (Hungarian
-translation).
-
-   Tamas also maintains a version of this file at
-http://www.datanet.hu/generations/linux/Changes.html (English version).
-
-   For people who prefer Japanese (thanks to Mitsuhiro Kojima): Kono
-bunshou no nihongo ban wa
-http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
-
-   Voyez le site http://www.linux-kheops.com/traduc/kernels/ pour la
-traduction francais (merci, David Bourgin).  (French translation)
-
-Last updated: November 5, 1996.
-Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
-
-Current Releases
-****************
-
-- Kernel modules        2.0.0
-- PPP daemon            2.2.0f
-- Dynamic linker (ld.so) 1.7.14
-- GNU CC                2.7.2.1
-- Binutils              2.7.0.3
-- Linux C Library       Stable:  5.2.18, Beta:  5.4.10
-- Linux C++ Library     2.7.2.1
-- Termcap               2.0.8
-- Procps                1.01
-- Gpm                   1.10
-- SysVinit              2.64
-- Util-linux            2.5
-- Mount                  2.5p
-- Net-tools              1.32-alpha
-- Kbd                    0.91
-
-Upgrade notes
-*************
-
-Network errors with recent kernels
-==================================
-
-   Many default network scripts are set up to add a route to the
-localhost at 127.0.0.1 at startup.  However, they do this incorrectly.
-To fix the error, which is now spotted by the kernel (causing many
-daemons to quit working), look for a line like `route add -net
-127.0.0.1' in your network configuration files and change it to `route
-add -net 127.0.0.0'.
-
-   This error is present in all Red Hat distributions through Red Hat
-3.03 (and derivative distributions like Caldera).  If you're running
-one of these, edit /etc/sysconfig/network-scripts/ifup-lo, changing the
-line `route add -net $(IPADDR)' to `route add -net 127.0.0.0' and you
-should be fine.
-
-   People have also reported problems due to the naming of the dummy
-network interface driver.  If the dummy driver is compiled into the
-kernel, its name is "dummy."  If the dummy driver is compiled as a
-module, its name is "dummy0."  Furthermore, more than one dummy driver
-can be loaded if compiled as a module.  Each subsequent loading of the
-driver adds a new dummy interface whose name is incremented by one
-("dummy1," "dummy2," etc.).
-
-Booting Changes
-===============
-
-   The boot support in 2.0.x (for arch/i386) has been enhanced so that
-it now can load bigger kernels (bzImage) and that the loaders now can
-load an initial ramdisk (initrd). For initrd see
-Documentation/initrd.txt. For building bigger kernels use one of the
-following make targets: bzImage, bzlilo, bzdisk (equivalent to make
-targets zImage, zlilo, and zdisk respectively). If you want or need to
-use the new features you'll need to upgrade your bootloaders.  Lilo can
-be found at ftp://lrcftp.epfl.ch/pub/linux/local/lilo/lilo.19.tar.gz.
-LOADLIN is at
-ftp://sunsite.unc.edu/pub/Linux/system/Linux-boot/lodlin16.tgz.  If
-you're using more unusual loaders like SysLinux or etherboot, the
-latest versions are 1.3 and 2.0, respectively.
-
-   Ramdisk support does not work with the latest kernels if ramdisk=0
-option is present.  Many older distributions (mainly Slackware) have
-this option in their lilo.config file.  Comment it out and re-run lilo
-if you need ramdisks.
-
-   The definition of SIOCSARP in /usr/include/linux/sockios.h was
-changed.  This means bootpd has to be re-compiled in order to work.
-
-   The kernel reboot method is now, by default, a cold reboot so that
-the kernel will work on systems that don't support other methods.  If
-you want to be able to do a warm reboot, add a reboot=warm option to
-lilo.conf.
-
-The Linux C Library
-===================
-
-   The latest stable Linux C Library release is 5.2.18.  If you upgrade
-to this from 5.0.9 or earlier, be sure to read the
-`release.libc-5.2.18' file, since GNU make and a few other fairly
-important utils can be broken by the upgrade.
-
-   The current (beta) Linux C Library release is 5.3.12. In this
-release there are some important changes that may cause troubles to
-buggy programs (programs that call free() on a pointer not returned by
-malloc() work with previous libc, but not with this release) so read the
-`release.libc-5.3.12' file carefully!  In the latest libc releases a
-dirent bug, which erroneously defined d->reclen to d->namlen if USE_GNU
-was defined, has been fixed.  Unfortunately, some GNU packages depend
-on this bug.  GNU make 3.xx is one of them.  To fix that you need to
-patch and recompile those programs (a patch for make is included in the
-file `release.libc-.5.3.9', and the address to obtain a precompiled
-binary is at the end of this file).
-
-   Also, the libc-5.3.x line has a known security hole relating to
-rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.10 is
-currently available as well, but it may have problems, so caveat emptor.
-
-   If you're getting an error message that is something to the effect of
-
-   `fcntl_setlk() called by process 123 with broken flock() emulation'
-
-   then you need to upgrade to at least libc-5.2.18 as well.  A proper
-(in other words, BSD-style ;-) flock system call was added to 2.0.x,
-and older libc's will now give this error.  It doesn't *really* matter,
-so you can just ignore it. If it really annoys you, upgrade libc (and
-recompile any static binaries you might have that are linked against
-the old libc).  If you're feeling lazy, just comment out
-
-   `                printk(KERN_WARNING
-"fcntl_setlk() called by process %d with broken flock()
-  emulation\n",                        current->pid);'
-
-   in linux/fs/locks.c and recompile.  If you're still running a.out,
-there's an unofficial libc-4.7.6 release out to which you can upgrade
-to fix this problem.  Libc is available from
-ftp://sunsite.unc.edu/pub/Linux/GCC/.
-
-GCC Signal 11 error
-===================
-
-   Many people have been reporting messages like the following,
-especially when compiling a new kernel:
-
-   `gcc:  Internal compiler error:  program cc1 got fatal signal 11'.
-
-   This is NOT a kernel bug.  Rather, these messages are generally
-caused by hardware problems.  See http://www.bitwizard.nl/sig11/ for
-the sig11 FAQ.
-
-   On the other hand, if you're using a gcc patched for Pentium
-optimization and are getting these errors, downgrade to a standard GNU
-gcc before assuming your hardware (or the kernel) is to blame.
-
-   On a related note, if you get random OOPses that don't seem to be
-related to anything and you have a motherboard with APM support, try
-disabling the APM support and/or compiling the kernel with APM support.
-
-Procps utilities
-================
-
-   Due to changes in the structure of the /proc filesystem, you need to
-upgrade procps to the latest release, currently 1.01.  Otherwise,
-you'll get floating point errors with some ps commands or other similar
-surprises.  Grab
-ftp://sunsite.unc.edu/pub/Linux/system/Status/ps/procps-1.01.tgz.
-
-Kernel Modules
-==============
-
-   Almost all drivers in 2.0.x can be modules, and kerneld is now
-incorporated into the kernel.  To take advantage of this, you'll need
-the latest version of the module support apps. These are available at
-http://www.pi.se/blox/modules/modules-2.0.0.tar.gz.  Note: If you try to
-load a module and get a message like
-
-   `gcc2_compiled, undefined Failed to load module!  The symbols from
-kernel 1.3.foo don't match 1.3.foo'
-
-   where `foo' is a number for a recent kernel, then it's definitely
-time to upgrade module utilities.
-
-   Another little tip: you can't have both a.out *and* ELF support
-compiled as modules.  Otherwise, you get a nice Catch-22 when you try
-to run insmod to install a.out/ELF support so you can run insmod ;-).
-If you have an all-ELF system, but need a.out for the occasional legacy
-app, then you can do a.out support as a module.  Otherwise, you should
-probably leave it in the kernel, and if you haven't gone ELF yet, you
-can probably say no to ELF support.  Similarly, any partitions that you
-have to mount at startup have to have their necessary file system and
-device drivers compiled into the kernel, so don't get grandiose ideas
-about going completely modular and then forget to compile ext2fs
-support and ide/SCSI drive support into your kernel ;-).
-
-Kernel messages
-===============
-
-   Kernel messages without a specific log level use the kernel's
-default log level.  In 1.2 kernels, the default log level was 6
-(information), while in 2.0.x kernels it is 4 (warning).  Adjust your
-configuration of syslogd appropriately (or edit printk.c in the kernel
-source ;-).
-
-PPP driver
-==========
-
-   You need to be running a pppd from ppp-2.2.0.tar.gz or greater.  The
-latest stable release is 2.2.0f and is available at
-ftp://sunsite.unc.edu/pub/Linux/system/Network/serial/ppp/ppp-2.2.0f.tar.gz.
-
-Named pipes (SysVinit)
-======================
-
-   Linux's handling of named pipes changed (it now does it The Right Way
-instead of the SunOS way ;-).  This broke some programs that depended
-on the SunOS behavior, most notably SysVinit.  If you're running 2.59
-or earlier, you will probably get a weird error on shutdown in which
-your computer shuts down fine but "INIT: error reading initrequest" or
-words to that effect scroll across your screen hundreds of times.  To
-fix, upgrade to
-ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz.
-
-   If you're trying to run NCSA httpd, you might have problems with
-pre-spawning daemons.  Upgrade to the latest release (1.5.2), available
-from http://hoohoo.ncsa.uiuc.edu/ or check out Apache
-(http://www.apache.org/).
-
-   The new named pipe behavior also causes problems with Hylafax.  If
-you're running the hylafax daemon, it will just keep eating up CPU time
-until you have no idle time free.  To fix this, edit port.h included
-with the Hylafax distribution and change the line
-
-   CONFIG_OPENFIFO="O_RDONLY"
-
-   to
-
-   CONFIG_OPENFIFO="O_RDWR"
-
-   A similar method (finding all named pipes opened read-only and
-changing them to read-write) will fix any program that is broken
-because of this change.
-
-File Locking (Sendmail)
-=======================
-
-   As of pre2.0.6 (aka 1.99.6), mixed-style file locking is no longer
-allowed.  For example, a file cannot be simultaneously locked with
-`flock' and `fcntl'.  See Documentation/locks.txt for all the gory
-details.  Among the programs this has impacted are older sendmails.  If
-you get a message that sendmail cannot lock aliases.dir (or other
-files), you'll need to upgrade to at least 8.7.x. The latest sendmail
-is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.2.tar.gz.
-
-Uugetty
-=======
-
-   Older uugettys will not allow use of a bidirectional serial line.  To
-fix this problem, upgrade to
-ftp://sunsite.unc.edu/pub/Linux/system/Serial/getty_ps-2.0.7i.tar.gz.
-
-Kbd
-===
-
-   For those of you needing non-ASCII character/font support, you should
-upgrade to ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/kbd-0.91.tar.gz.
-
-Mount
-=====
-
-   The mount util is distributed as part of util-linux, which is
-currently at release 2.5.  Some may find, especially when using the
-loop or xiafs file system, NFS, or automounting, that they need to
-upgrade to the latest release of mount, available from
-ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5p.tar.gz.
-
-Console
-=======
-
-   The Linux console type has changed.  If your setup is old enough
-that you have problems, you'll need to update your termcap.  To fix,
-add linux to one of the types in /etc/termcap or snoop around
-http://www.ccil.org/~esr/ncurses.html (reputedly the latest universal
-termcap maintainer).  You may also need to update terminfo by running
-the following as root:
-
-   ln -s /usr/lib/terminfo/l/linux /usr/lib/terminfo/c/console
-
-   Better yet, just get the latest official Linux termcap from
-ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz.  If you
-upgrade to this release read the `README' file contained into the
-package to get some important information about the `tgetent' function
-changes!  Note that there is now a fixed version at
-ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.fix.  If some of your
-apps complain that termcap entries are too long and you don't need some
-of the more esoteric terms in the standard 2.0.8 termcap, just download
-termcap-2.0.8.fix and move it to /etc/termcap.
-
-   Also, the console driver is now responsible for keeping track of
-correspondence between character codes and glyph bitmaps.  If you
-encounter problems, try `loadunimap def' to get back the default
-correspondence.
-
-Hdparm
-======
-
-   Hdparm has been upgraded to take advantage of the latest features of
-the kernel drivers.  The latest non-beta version can be found at
-ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.1.tar.gz.
-
-IP Accounting
-=============
-
-   All IP packets coming in or going out via one of the network
-interfaces are now passing the accounting chain.  So, packets being
-forwarded are passing this chain twice.  Since pre2.0.7 (aka 1.99.7),
-accounting rules can be defined so that they will only match in one
-direction (either incoming or outgoing).
-
-   There also exists a possibility to match on device names and/or
-device addresses, so that only packets coming in/going out via that
-device (network interface) match with a rule.  You'll need to get
-ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to
-use this.
-
-IP Firewalls
-============
-
-   The IP firewall code has been changed drastically for 2.0.x. There
-are now 3 categories of firewall rules: one for incoming packets, one
-for outgoing packets, and one for packets being forwarded.  There also
-exists a possibility to match on device names and/or device addresses,
-so that only packets coming in/going out via that device (network
-interface) match with a rule.  This is especially useful to prevent
-spoofing.  You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
-
-IP Masquerading
-===============
-
-   IP masquerading is now part of the standard kernel.  However, you
-always need to load separate modules (ip_masq_ftp.o and/or
-ip_masq_irc.o) if you are going to use FTP or IRC in combination with
-masquerading.  You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
-
-ISDN support
-============
-
-   The new kernels support ISDN.  You'll need ISDN utils available from
-ftp://ftp.franken.de/pub/isdn4linux/v2.0/isdn4k-utils-2.0.tar.gz to try
-this.
-
-Frame Relay
-===========
-
-   Frame relay support for Linux is now available as well.  Currently,
-only Sangoma cards are supported, but the interface is such that others
-will be as drivers become available.  To use this, grab
-ftp://linux.invlogic.com/pub/fr/frad-0.15.tgz (soon to be
-frad-0.20.tgz).  Another package of interest is
-ftp://linux.invlogic.com/pub/routing/routing.tgz (which allows Linux to
-make routing decisions based on packet source).
-
-Networking
-==========
-
-   Some of the /proc/net entries have changed.  You'll need to upgrade
-to the latest net-tools in
-ftp://ftp.inka.de/pub/comp/Linux/networking/NetTools/, where the latest
-is currently net-tools-1.32-alpha.tar.gz.  See
-http://www.inka.de/sites/lina/linux/NetTools/index_en.html for more
-information.  Note that there is currently no ipfw (which is part of
-net-tools) which works with 2.0.x kernels.  If you need its functions,
-learn how to use ipfwadm or patch ipfw to get it to work (ipfw's current
-maintainer does not currently have time to fix it).
-
-Xntpd
-=====
-
-   Older versions of xntpd will not work with the latest kernels.
-Upgrade to xntp3.5f.tar.Z, available from
-ftp://louie.udel.edu/pub/ntp/xntp3.5f.tar.Z.
-
-Sound driver
-============
-
-   The sound driver was upgraded in the 2.0.x kernels, breaking vplay.
-To fix this problem, get a new version of the sndkit from
-ftp://ftp.best.com/pub/front/tasd/snd-util-3.5.tar.gz.  Some users
-report that various other sound utils (cdd2wav-sbpcd, for example) need
-to be recompiled before they will work with the new kernels.
-
-Tcsh
-====
-
-   If tcsh acts funny, get the source from
-ftp://anise.ee.cornell.edu/pub/tcsh and add #define SYSMALLOC in
-config_f.h before recompiling tcsh.  Binaries can be found in
-ftp://sunsite.unc.edu/pub/Linux/system/Shells/ and a corrected one will
-probably wind up there eventually.
-
-Make
-====
-
-   If make no longer works, you need to read the release notes for the
-libc you upgraded to.  The latest libc and release notes can be found at
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC.  This is NOT an error due
-to the kernel, though many people have mistakenly thought it is.  When
-you upgrade to libc-5.3.9, you have to patch make to get it to work.
-All of this is documented in the release notes with libc.  Upgrading
-libc can also break xterm support.  If it does, you need to recompile
-xterm.
-
-Loop device
-===========
-
-   2.0.x kernels include loop device support which lets you mount a
-file as a file system, which can allow for all sorts of cool things
-like encrypted file systems and such.  To use it, you'll need a
-modified version of mount from
-ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz; preliminary work
-on encrypted file system support can be found in
-ftp.funet.fi:/pub/Linux/BETA/loop/des.1.tar.gz.
-
-Multiple device
-===============
-
-   Multiple device support (allowing you to group several partitions
-into one logical device) has also been added.  Check out
-ftp://sweet-smoke.ufr-info-p7.ibp.fr/pub/Linux/md035.tar.gz to try this
-out.
-
-Arp
-===
-
-   Arp daemon support has been added.  Check out
-http://www.loran.com/~layes/arpd/index.html for more info and
-http://www.loran.com/~layes/arpd/arpd-1.0.2.tar.gz for a copy of arpd.
-
-Quota
-=====
-
-   Quota support has also been added.  You need to get quotas-1.55 from
-ftp://ftp.funet.fi/pub/Linux/kernel/src/subsystems/quota/all.tar.gz. You
-may need to copy its mntent.h over to /usr/include/mntent.h to get it to
-compile.
-
-Process Accounting
-==================
-
-   Process accounting support has also been integrated into the new
-kernels. To use this feature, you'll need to get
-ftp://iguana.hut.fi/pub/linux/Kernel/process_accounting/acct_1.3.73.tar.gz.
-
-Bdflush and Updated
-===================
-
-   Bdflush has also been integrated into the new kernels, so those of
-you using it on older systems no longer need to hunt for the patches to
-implement it once you upgrade to 2.0.x.  You do still need to run the
-update daemon, however.  You should probably upgrade to the latest
-updated, currently
-ftp://sunsite.unc.edu/pub/Linux/system/Daemons/updated-1.2.tar.gz.  This
-(and later) versions will not spawn a bdflush daemon, since that is now
-done by the kernel (kflushd).  If you upgrade, be sure to leave update
-in your init scripts and remove bdflush.
-
-APM support
-===========
-
-   Advanced Power Management (APM) support has been added to the kernel
-as well.  APM, which is primarily of use in laptops, provides access to
-battery status information and may help to conserve battery power.  The
-support files can be found in
-ftp://tsx-11.mit.edu/pub/linux/packages/laptops/apm/apmd-2.4.tar.gz
-
-iBCS and Dosemu
-===============
-
-   For a version of iBCS that works with 2.0.x kernels, grab
-ftp://tsx-11.mit.edu/pub/linux/BETA/ibcs2/ibcs-2.0-960610.tar.gz
-
-   For a version of Dosemu that works (well, at least as well as DOS
-ever works ;-), get
-ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.64.0.3.tgz
-or check out http://www.ednet.ns.ca/auto/rddc. Be sure to follow the
-instructions in README.newkernels about patching your include files, or
-it will not compile.
-
-Mtools and Fdutils
-==================
-
-   The floppy ioctl numbering scheme has changed for 2.0.x.  For
-backwards compatibility, the old system was supported through 1.3.x and
-will generate a warning in 2.0.  In 2.1.x, the old scheme will
-disappear entirely.
-
-   To avoid trouble (or at least annoying messages), you'll need to
-recompile any programs which emit floppy ioctls, including mtools and
-fdutils.  For mtools, get
-ftp://sunsite.unc.edu/pub/Linux/utils/disk-management/mtools-3.0.src.tar.gz
-and for fdutils, get
-ftp://sunsite.unc.edu/pub/Linux/system/Misc/fdutils-4.3.src.tar.gz.
-
-   In the future, fdformat might disappear entirely, so get used to
-using superformat instead.
-
-Cyclades Serial Driver
-======================
-
-   The Cyclades driver has been changed so that the minor numbers start
-at 0 instead of 32 (for example, ttyC0 should be major 19, minor 0 for
-2.0.x kernels; in older kernels, it would have been major 19, minor
-32).  Use mknod or a sufficiently new version of MAKEDEV to fix this.
-
-NCR 53c810 SCSI Driver
-======================
-
-   Drivers for this card are now included in the standard linux source.
-However, they require Perl to be installed before they will compile.
-As far as I know, this is the only code in the kernel source that
-requires Perl to compile.  If your kernel compile fails and you happen
-to have included this driver in your configuration, make sure you have
-Perl installed.
-
-Perl
-====
-
-   While we're on the subject, changes made for the 2.0.x series cause
-the connect() Perl (both 4 and 5) call to time out while connecting to
-remote systems.  The problem is not actually in the connect() call;
-rather, the optional bind() call usually used with connect() causes the
-problem.  Remove the bind() call and your Perl scripts should connect.
-
-   Also, Perl scripts using the readdir call now misbehave if you're
-using an old version of Perl, due to changes in libc.  Upgrade to a
-more current Perl to avoid any unpleasantness.
-
-Groff
-=====
-
-   Those of you running Slackware may experience weirdness with man
-pages due to changes in groff.  If your man pages display <AD> for -
-when present at the end of a line, try setting an appropriate value
-(many have reported success with "latin1", for example) for the
-environmental variable LESSCHARSET.  Another, and probably better,
-solution is to edit the file /usr/lib/man.config and change all
-`-Tlatin1' options to `-Tascii'.  An alternate solution, for those of
-you who can't reformat your man files in .../cat* directories is to
-edit /usr/lib/man.config, setting the PAGER to `PAGER
-(LESSCHARSET=latin1;export LESSCHARSET;/usr/bin/less -is)'.
-
-E2fsprogs
-=========
-
-   e2fsprogs 1.02 will work with the latest kernels, but it cannot be
-compiled on them.  If you need (or want) to compile your own copy,
-you'll need to get the latest version, currently available at
-ftp://tsx-11.mit.edu/pub/linux/packages/ext2fs/e2fsprogs-1.06.tar.gz.
-
-How to know the version of the installed programs
-*************************************************
-
-   There are some simple methods useful to know the version of the
-installed programs and libraries.  The SysVinit version display
-requires that you be logged in as root.
-
-GNU CC: gcc -v and gcc --version
-PPP: pppd -h (wrong but it show the version)
-Libc: ls -l /lib/libc.so.5
-Libc++: ls -l /usr/lib/libg++.so
-Binutils: ld -v
-ldd: ldd -v and ldd -V
-termcap: ls -l /lib/libtermcap.so.*
-modules: insmod -V
-procps: ps --version
-SysVinit: cat /proc/`cat /var/run/syslog.pid`/environ|strings|awk '$1 ~
-/INIT_VERSION/ {print}'
-
-Where to get the files
-**********************
-
-Binutils
-========
-
-ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/binutils-2.7.0.3.bin.tar.gz
-Installation notes:
-ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/release.binutils-2.7.0.3
-
-GNU CC
-======
-
-ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.1.bin.tar.gz
-Installation notes:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.1
-
-Linux C Library
-===============
-
-The stable 5.2.18 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.2.18.bin.tar.gz
-Installation notes for 5.2.18:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
-
-The latest 5.4.10 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.10.bin.tar.gz
-Installation notes for 5.4.10:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.10
-
-Patched make sources:
-ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz
-Patched make binary:
-ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74-direntfix-elf.tgz
-
-Linux C++ Library
-=================
-
-ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz
-Installation notes:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1
-
-Dynamic Linker
-==============
-
-ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.7.14.tar.gz
-
-Termcap Library
-===============
-
-ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz
-
-Modules utilities
-=================
-
-The latest public release:
-ftp://sunsite.unc.edu/pub/Linux/kernel/modules-2.0.0.tar.gz
-
-PPP Daemon and utilities
-========================
-
-The latest public release:
-ftp://sunsite.unc.edu/pub/Linux/system/Network/serial/ppp/ppp-2.2.0f.tar.gz
-
-Procps utilities
-================
-
-ftp://sunsite.unc.edu/pub/Linux/system/Status/ps/procps-1.01.tgz
-
-Gpm mouse utilities
-===================
-
-ftp://iride.unipv.it/pub/gpm/gpm-1.10.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/system/Daemons/gpm-1.10.tar.gz
-
-SysVinit utilities
-==================
-
-ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz
-
-Util-linux
-==========
-
-ftp://sunsite.unc.edu/pub/Linux/system/Misc/util-linux-2.5.tar.gz
-
-Mtools
-======
-
-ftp://sunsite.unc.edu/pub/Linux/utils/disk-management/mtools-3.0.src.tar.gz
-
-Fdutils
-=======
-
-ftp://sunsite.unc.edu/pub/Linux/system/Misc/fdutils-4.3.src.tar.gz
-
-Other Info
-==========
-
-   Please remember that most of these utils are available on your
-favorite local linux mirror.  If you can, please get them from a closer
-site before checking sunsite.
-
-   Also, for those of you running Red Hat (or RPM on a different
-distribution), most of these are available in RPM format.  Check around
-your favorite Red Hat mirror site before installing the non-RPM
-version.  Remember, you might need to use the -force option to get the
-upgrade to install.  Almost everything you need is available in
-ftp://ftp.redhat.com/pub/current/i386/updates/2.0-kernel/ and its
-mirrors.
-
-   For others, David Bourgin has put together a package of everything
-necessary to quickly and easily upgrade to 2.0.x.  See
-ftp://ftp.wsc.com/pub/freeware/linux/update.linux/ for more information
-and the files.  This package also includes many bug-fixes, such as the
-latest sendmail. There's also an alternate lightweight termcap in the
-same directory that works well for many people.
-
-Please send info about any other packages that 2.0.x "broke" or about
-any new features of 2.0.x that require extra or new packages for use to
-Chris Ricker (gt1355b@prism.gatech.edu).  I generate this from a
-modified texinfo setup, so you don't need to bother generating a diff
-against the current version before you send the additional information
-to me.
-
+Intro
+=====
+
+This document is designed to provide a list of the minimum levels of
+software necessary to run the 2.1.x kernels, as well as provide brief
+instructions regarding any other "Gotchas" users may encounter when
+trying life on the Bleeding Edge.  If upgrading from a pre-2.0.x
+kernel, please consult the Changes file included with 2.0.x kernels for
+additional information; most of that information will not be repeated
+here.  Basically, this document assumes that your system is already
+functional and running at least 2.0.x.
+
+   It is originally based on my "Changes" file for 2.0.x kernels and
+therefore owes credit to the same people as that file (Jared Mauch,
+Axel Boldt, Alessandro Sigala, and countless other users all over the
+'net).  Please feel free to submit changes, corrections, gripes,
+flames, money, etc. to me (gt1355b@prism.gatech.edu).  If you do so,
+you don't need to bother doing so in the form of a diff, as this is
+generated by texinfo so a diff is useless anyway (though I can
+incorporate one by hand if you insist upon sending it that way ;-).
+
+Last updated: November 13, 1996.
+Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
+
+Current Minimal Requirements
+****************************
+
+   Upgrade to at *least* these software revisions before thinking you've
+encountered a bug!
+
+- Kernel modules        2.0.0
+- Gnu C                 2.7.2.1
+- Binutils              2.7.0.3
+- Linux C Library       5.4.12
+- Linux C++ Library     2.7.2.1
+- Procps                1.01
+- SysVinit              2.64
+- Util-linux            2.5
+- Mount                  2.5p
+- Net-tools              1.32-alpha
+- Kbd                    0.91
+
+Upgrade notes
+*************
+
+General Information
+===================
+
+   <CTRL><ALT><DEL> now performs a cold reboot instead of a warm reboot
+for increased hardware compatibility.  If you want a warm reboot and
+know it works on your hardware, add a "reboot=warm" command line option
+in Lilo.
+
+Libc
+====
+
+   Linux-2.1.x is ELF-only.  You can still compile a.out apps if you
+really want, but your kernel must be compiled ELF.  If you can't
+currently compile ELF, consult the ELF howto at
+http://sunsite.unc.edu/mdw/HOWTO/ELF-HOWTO.html and upgrade your system
+accordingly.
+
+   For modules to work, you need to be running libc-5.4.7 or greater.
+Since updates to libc fix other problems as well (security flaws, for
+example) and since 5.4.7 is missing a few needed symbols, try to get
+the latest 5.4.x you can.  Currently, that is libc-5.4.12.
+
+How to know the version of the installed programs
+*************************************************
+
+   There are some simple methods useful to know the version of the
+installed programs and libraries.  The SysVinit version display
+requires that you be logged in as root.
+
+Gnu C: gcc -v or gcc --version
+Libc: ls -l /lib/libc.so.*
+Libc++: ls -l /usr/lib/libg++.so.*
+Binutils: ld -v
+modules: insmod -V
+procps: ps --version
+SysVinit: cat /proc/`cat /var/run/syslog.pid`/environ|strings|awk '$1 ~
+/INIT_VERSION/ {print}'
+
+Where to get the files
+**********************
+
+Binutils
+========
+
+ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/binutils-2.7.0.3.bin.tar.gz
+Installation notes:
+ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/release.binutils-2.7.0.3
+
+Gnu C
+=====
+
+ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.1.bin.tar.gz
+Installation notes:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.1
+
+Linux C Library
+===============
+
+The stable 5.2.18 release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.2.18.bin.tar.gz
+Installation notes for 5.2.18:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
+
+The latest 5.4.12 release (when it gets there):
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.12.bin.tar.gz
+Installation notes for 5.4.12:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.12
+
+Linux C++ Library
+=================
+
+ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz
+Installation notes:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1
+
+Dynamic Linker
+==============
+
+ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.7.14.tar.gz
+
+Modules utilities
+=================
+
+ftp://sunsite.unc.edu/pub/Linux/kernel/modules-2.0.0.tar.gz
+
+Procps utilities
+================
+
+ftp://sunsite.unc.edu/pub/Linux/system/Status/ps/procps-1.01.tgz
+
+SysVinit utilities
+==================
+
+ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz
+
+Util-linux
+==========
+
+ftp://sunsite.unc.edu/pub/Linux/system/Misc/util-linux-2.5.tar.gz
+
+Other Info
+==========
+
+   Please remember that most of these utils are available on your
+favorite local linux mirror.  If you can, please get them from a closer
+site before checking sunsite.
+
+   Also, for those of you running Red Hat (or RPM on a different
+distribution), most of these are available in RPM format.  Check around
+your favorite Red Hat mirror site before installing the non-RPM
+version.  Remember, you might need to use the -force option to get the
+upgrade to install.  Almost everything you need is available in
+ftp://ftp.redhat.com/pub/contrib/
+
+   For others, David Bourgin has put together a package of everything
+necessary to quickly and easily upgrade to 2.1.x.  See
+ftp://ftp.wsc.com/pub/freeware/linux/update.linux/kernel-v2.1.x/ for
+more information and the files.
+
+Please send info about any other packages that 2.1.x "broke" or about
+any new features of 2.1.x that require extra or new packages for use to
+Chris Ricker (gt1355b@prism.gatech.edu).
+
index fbe5028..884290c 100644 (file)
@@ -1243,6+1243,13 @@ CONFIG_BLK_DEV_SR
   say M here and read Documentation/modules.txt and
   Documentation/scsi.txt .
 
+Enable vendor-specific extentions (for SCSI CDROM)
+CONFIG_BLK_DEV_SR_VENDOR
+  This enables the usage of vendor specific SCSI commands. This is
+  required for some stuff which is newer than the SCSI-II standard,
+  most important is the multisession CD support. You'll probably want
+  to say y here, unless you have a _real old_ CD-ROM drive.
+
 SCSI generic support
 CONFIG_CHR_DEV_SG
   If you want to use SCSI scanners, synthesizers or CD-writers or just
index b34f50b..559368e 100644 (file)
@@ -42,7+42,7 @@ foo \kill}%
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
-\date{Last revised: July 9, 1996}
+\date{Last revised: November 13, 1996}
 \maketitle
 %
 \noindent
@@ -179,7+179,11 @@ reply.
 \major{52}{}{char }{Spellcaster DataComm/BRI ISDN card}
 \major{53}{}{char }{BDM interface for remote debugging MC683xx microcontrollers}
 \major{54}{}{char }{Electrocardiognosis Holter serial card}
-\major{55}{--59}{}{Unallocated}
+\major{55}{}{char }{DSP56001 digital signal processor}
+\major{56}{}{char }{Apple Desktop Bus}
+\major{57}{}{char }{Hayes ESP serial card}
+\major{58}{}{char }{Hayes ESP serial card -- alternate devices}
+\major{59}{}{}{Unallocated}
 \major{60}{--63}{}{Local/experimental use}
 \major{64}{--119}{}{Unallocated}
 \major{120}{--127}{}{Local/experimental use}
@@ -453,6+457,7 @@ physical disks.
        \minor{5}{/dev/atarimouse}{Atari mouse}
        \minor{6}{/dev/sunmouse}{Sun mouse}
        \minor{7}{/dev/amigamouse1}{Second Amiga mouse}
+       \minor{8}{/dev/smouse}{Simple serial mouse driver}
        \minor{128}{/dev/beep}{Fancy beep device}
        \minor{129}{/dev/modreq}{Kernel module load request}
        \minor{130}{/dev/watchdog}{Watchdog timer port}
@@ -1116,7+1121,35 @@ $<$mseritan@ottonel.pub.ro$>$ to transfer data from Holter 24-hour
 heart monitoring equipment.
 
 \begin{devicelist}
-\major{55}{--59}{}{Unallocated}
+\major{55}{}{char }{DSP56001 digital signal processor}
+       \minor{0}{/dev/dsp56k}{First DSP56001}
+\end{devicelist}
+
+\begin{devicelist}
+\major{56}{}{char }{Apple Desktop Bus}
+       \minor{0}{/dev/adb}{ADB bus control}
+\end{devicelist}
+
+\noindent
+Additional devices will be added to this number, all starting with
+{\file /dev/adb}.
+
+\begin{devicelist}
+\major{57}{}{char }{Hayes ESP serial card}
+       \minor{0}{/dev/ttyP0}{First ESP port}
+       \minor{1}{/dev/ttyP1}{Second ESP port}
+       \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{58}{}{char }{Hayes ESP serial card -- alternate devices}
+       \minor{0}{/dev/cup0}{Callout device corresponding to {\file ttyP0}}
+       \minor{1}{/dev/cup1}{Callout device corresponding to {\file ttyP1}}
+       \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{59}{}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
@@ -1182,9+1215,9 @@ It is recommended that these links exist on all systems:
 \link{/dev/ramdisk}{ram0}{symbolic}{Backward compatibility}
 \link{/dev/ftape}{rft0}{symbolic}{Backward compatibility}
 \link{/dev/scd?}{sr?}{hard}{Alternate name for CD-ROMs}
-%\link{/dev/fd?H*}{fd?D*}{hard}{Compatible floppy formats}
-%\link{/dev/fd?E*}{fd?D*}{hard}{Compatible floppy formats}
-%\link{/dev/fd?E*}{fd?H*}{hard}{Compatible floppy formats}
+\link{/dev/fd?D*}{fd?u*}{hard}{Backward compatibility}
+\link{/dev/fd?H*}{fd?u*}{hard}{Backward compatibility}
+\link{/dev/fd?E*}{fd?u*}{hard}{Backward compatibility}
 \end{nodelist}
 
 \subsection{Locally defined links}
index 81fbd64..5fd527c 100644 (file)
@@ -2,7+2,7 @@
 
             Maintained by H. Peter Anvin <hpa@zytor.com>
 
-                    Last revised: July 9, 1996
+                  Last revised: November 13, 1996
 
 This list is the successor to Rick Miller's Linux Device List, which
 he stopped maintaining when he got busy with other things in 1993.  It
@@ -269,6+269,7 @@ reply.
                  5 = /dev/atarimouse   Atari mouse
                  6 = /dev/sunmouse     Sun mouse
                  7 = /dev/amigamouse1  Second Amiga mouse
+                 8 = /dev/smouse       Simple serial mouse driver
                128 = /dev/beep         Fancy beep device
                129 = /dev/modreq       Kernel module load request
                130 = /dev/watchdog     Watchdog timer port
@@ -785,7+786,26 @@ reply.
                <mseritan@ottonel.pub.ro> to transfer data from Holter
                24-hour heart monitoring equipment.
 
- 55-59         UNALLOCATED
+ 55 char       DSP56001 digital signal processor
+                 0 = /dev/dsp56k       First DSP56001
+
+ 56 char       Apple Desktop Bus
+                 0 = /dev/adb          ADB bus control
+
+               Additional devices will be added to this number, all
+               starting with /dev/adb.
+
+ 57 char       Hayes ESP serial card
+                 0 = /dev/ttyP0        First ESP port
+                 1 = /dev/ttyP1        Second ESP port
+                     ...
+
+ 58 char       Hayes ESP serial card - alternate devices
+                 0 = /dev/cup0         Callout device corresponding to ttyP0
+                 1 = /dev/cup1         Callout device corresponding to ttyP1
+                     ...
+
+ 59            UNALLOCATED
 
  60-63         LOCAL/EXPERIMENTAL USE
                Allocated for local/experimental use.  For devices not
index 93e9219..5672f52 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6+1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 9
+SUBLEVEL = 10
 
 ARCH = i386
 
@@ -285,6+285,7 @@ modules_install:
        if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \
        if [ -f NET_MODULES   ]; then inst_mod NET_MODULES   net;   fi; \
        if [ -f IPV4_MODULES  ]; then inst_mod IPV4_MODULES  ipv4;  fi; \
+       if [ -f IPV6_MODULES  ]; then inst_mod IPV6_MODULES  ipv6;  fi; \
        if [ -f SCSI_MODULES  ]; then inst_mod SCSI_MODULES  scsi;  fi; \
        if [ -f FS_MODULES    ]; then inst_mod FS_MODULES    fs;    fi; \
        if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \
index 591eb73..0e4a431 100644 (file)
@@ -102,6+102,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_ST is not set
 CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 
 #
@@ -123,9+124,9 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
 # CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_NCR53C406A is not set
@@ -193,6+194,7 @@ CONFIG_NFS_FS=y
 CONFIG_ISO9660_FS=y
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
+# CONFIG_AFFS_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
index e702893..c230afb 100644 (file)
@@ -1,5+1,5 @@
 /*
- * arch/alpha/lib/strlen_user.S
+ * arch/alpha/lib/__strlen_user.S
  *
  * Just like strlen except returns -EFAULT if an exception occurs
  * before the terminator is found.
        99: x,##y;                      \
        .section __ex_table,"a";        \
        .gprel32 99b;                   \
-       lda zero, $exception-99b(v0);   \
+       lda zero, $exception-99b(zero); \
        .text
 
 
        .set noat
        .text
 
-       .globl strlen_user
-       .ent strlen_user
+       .globl __strlen_user
+       .ent __strlen_user
        .frame sp, 0, ra
 
        .align 3
-strlen_user:
+__strlen_user:
        .prologue 0
 
        EX( ldq_u t0, 0(a0) )   # load first quadword (a0 may be misaligned)
@@ -34,7+34,7 @@ strlen_user:
        insqh   t1, a0, t1
        andnot  a0, 7, v0
        or      t1, t0, t0
-       nop                     # dual issue the next two on ev5
+       subq    a0, 1, a0       # return "1+strlen" (0 for exception)
        cmpbge  zero, t0, t1    # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
        bne     t1, $found
 
@@ -58,8+58,10 @@ $found:      negq    t1, t2          # clear all but least set bit
        nop                     # dual issue next two on ev4 and ev5
 
        subq    v0, a0, v0
+       ret
 
 $exception:
+       mov     zero, v0
        ret
 
-       .end strlen_user
+       .end __strlen_user
index 3431a9f..503b0cc 100644 (file)
@@ -25,7+25,7 @@ zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
 
 bzImage: $(CONFIGURE) bbootsect setup compressed/bvmlinux tools/bbuild
        if hash $(ENCAPS) 2> /dev/null; then \
-         $(OBJDUMP) $(OBJDUMP_FLAGS) -o $(IMAGE_OFFSET) compressed/bvmlinux > compressed/bvmlinux.out; \
+         $(OBJDUMP) $(OBJDUMP_FLAGS) -o $(BZIMAGE_OFFSET) compressed/bvmlinux > compressed/bvmlinux.out; \
        else \
          $(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out; \
        fi
index a11f330..d84faf2 100644 (file)
@@ -20,6+20,7 @@ static struct symbol_table arch_symbol_table = {
        X(dump_thread),
        X(dump_fpu),
        X(ioremap),
+       X(iounmap),
        XNOVERS(__down_failed),
        XNOVERS(__up_wakeup),
 #ifdef __SMP__
index e32082e..611e151 100644 (file)
@@ -1013,7+1013,7 @@ static void setup_DMA(void)
                FDCS->reset = 1;
                return;
        }
-       if ((long) raw_cmd->kernel_data % 512){
+       if (((unsigned long) raw_cmd->kernel_data) % 512){
                printk("non aligned address: %p\n", raw_cmd->kernel_data);
                cont->done(0);
                FDCS->reset=1;
@@ -2541,7+2541,8 @@ static int make_raw_rw_request(void)
                }
                /* 64 kb boundaries */
                if (CROSS_64KB(CURRENT->buffer, max_size << 9))
-                       max_size = (K_64 - ((long) CURRENT->buffer) % K_64)>>9;
+                       max_size = (K_64 - 
+                                   ((unsigned long)CURRENT->buffer) % K_64)>>9;
                direct = transfer_size(ssize,max_sector,max_size) - sector_t;
                /*
                 * We try to read tracks, but if we get too many errors, we
index 36e8629..b3092be 100644 (file)
@@ -2647,8+2647,8 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        return nslots;
 }
 
-
-void ide_cdrom_setup (ide_drive_t *drive)
+static
+int ide_cdrom_setup (ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
        int nslots;
@@ -2750,8+2750,12 @@ void ide_cdrom_setup (ide_drive_t *drive)
 
        nslots = ide_cdrom_probe_capabilities (drive);
 
-       if (ide_cdrom_register (drive, nslots))
-               printk ("%s: Can't register\n", drive->name);
+       if (ide_cdrom_register (drive, nslots)) {
+               printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+               info->devinfo.handle = NULL;
+               return 1;
+       }
+       return 0;
 }
 
 /* Forwarding functions to generic routines. */
@@ -2765,13+2769,22 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
 
 int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
 {
-       return cdrom_fops.open (ip, fp);
+       int rc;
+
+       MOD_INC_USE_COUNT;
+       rc = cdrom_fops.open (ip, fp);
+       if (rc) {
+               drive->usage--;
+               MOD_DEC_USE_COUNT;
+       }
+       return rc;
 }
 
 void ide_cdrom_release (struct inode *inode, struct file *file,
                        ide_drive_t *drive)
 {
        cdrom_fops.release (inode, file);
+       MOD_DEC_USE_COUNT;
 }
 
 int ide_cdrom_check_media_change (ide_drive_t *drive)
@@ -2785,6+2798,7 @@ int ide_cdrom_check_media_change (ide_drive_t *drive)
 int ide_cdrom_cleanup(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
+       struct cdrom_device_info *devinfo = &info->devinfo;
 
        if (ide_unregister_subdriver (drive))
                return 1;
@@ -2792,6+2806,8 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
                kfree (info->sector_buffer);
        if (info->toc != NULL)
                kfree (info->toc);
+       if (devinfo->handle == drive && unregister_cdrom (devinfo))
+               printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
        kfree (info);
        drive->driver_data = NULL;
        return 0;
@@ -2860,10+2876,17 @@ int ide_cdrom_init (void)
                        kfree (info);
                        continue;
                }
-               failed--;
                memset (info, 0, sizeof (struct cdrom_info));
                drive->driver_data = info;
-               ide_cdrom_setup (drive);
+               DRIVER(drive)->busy++;
+               if (ide_cdrom_setup (drive)) {
+                       DRIVER(drive)->busy--;
+                       if (ide_cdrom_cleanup (drive))
+                               printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
+                       continue;
+               }
+               DRIVER(drive)->busy--;
+               failed--;
        }
        ide_register_module(&ide_cdrom_module);
        MOD_DEC_USE_COUNT;
index b883d8a..3249929 100644 (file)
@@ -90,11+90,11 @@ endif #CONFIG_GSCD
 
 ifeq ($(CONFIG_CM206),y)
 L_OBJS += cm206.o
-C = 1 
+USE_GENERIC_CD=1
 else
   ifeq ($(CONFIG_CM206),m)
   M_OBJS += cm206.o
-  CM = 1
+    USE_MODULAR_GENERIC_CD=1
   endif
 endif #CONFIG_CM206
 
@@ -128,6+128,14 @@ else
   endif
 endif #CONFIG_ISP16_CDI
 
+ifeq ($(CONFIG_BLK_DEV_SR),y)
+USE_GENERIC_CD=1
+else
+  ifeq ($(CONFIG_BLK_DEV_SR),m)
+    USE_MODULAR_GENERIC_CD=1
+  endif
+endif #SCSI CDROM DRIVER
+
 ifeq ($(CONFIG_BLK_DEV_IDECD),y)
 USE_GENERIC_CD=1
 else
index 14eaf0b..1a12acc 100644 (file)
@@ -268,13+268,11 @@ int cdrom_media_changed(kdev_t dev)
    meaningful format indicated above.
  */
 
-#undef current                          /* set in sched.h */
-
 static
 void sanitize_format(union cdrom_addr *addr,
-                     u_char * current, u_char requested)
+                     u_char * curr, u_char requested)
 {
-        if (*current == requested)
+        if (*curr == requested)
                 return;                 /* nothing to be done! */
         if (requested == CDROM_LBA) {
                 addr->lba = (int) addr->msf.frame +
@@ -287,7+285,7 @@ void sanitize_format(union cdrom_addr *addr,
                 addr->msf.second = lba % 60;
                 addr->msf.minute = lba / 60;
         }
-        *current = requested;
+        *curr = requested;
 }
 
 /* All checking and format change makes this code really hard to read!
index 2b868e3..8963881 100644 (file)
        07 July 1995 Modifications by Andrew J. Kroll
 
        Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
+
+       Michael K. Johnson <johnsonm@redhat.com> added retries on open
+       for slow drives which take a while to recognize that they contain
+       a CD.
 */
 
 #include <linux/module.h>
@@ -1095,6+1099,7 @@ int
 mcd_open(struct inode *ip, struct file *fp)
 {
        int st;
+       int count = 0;
 
        if (mcdPresent == 0)
                return -ENXIO;                  /* no hardware */
@@ -1106,9+1111,16 @@ mcd_open(struct inode *ip, struct file *fp)
 
        mcd_invalidate_buffers();
 
-       st = statusCmd();                       /* check drive status */
-       if (st == -1)
-               return -EIO;                    /* drive doesn't respond */
+       do {
+               st = statusCmd();               /* check drive status */
+               if (st == -1)
+                       return -EIO;            /* drive doesn't respond */
+               if ((st & MST_READY) == 0) {    /* no disk? wait a sec... */
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + HZ;
+                       schedule();
+               }
+       } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
 
        if ((st & MST_READY) == 0)              /* no disk in drive */
        {
index 08fd06e..71f60ba 100644 (file)
@@ -1,3+1,9 @@
+Thu Nov 14 00:06:09 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+       * serial.c (autoconfig): Fix autoconfiguration problems;
+               info->flags wasn't getting initialized from the state
+               structure.  Put in more paranoid test for the 16750.
+
 Fri Nov  8 20:19:50 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * n_tty.c (n_tty_flush_buffer): Only call driver->unthrottle() if
index 40860ac..23a99a6 100644 (file)
 #include <asm/bitops.h>
 
 static char *serial_name = "Serial driver";
-static char *serial_version = "4.20";
+static char *serial_version = "4.21";
 
 DECLARE_TASK_QUEUE(tq_serial);
 
@@ -2687,7+2687,7 @@ static int get_auto_irq(struct async_struct *info)
        (void)serial_inp(info, UART_IIR);
        (void)serial_inp(info, UART_MSR);
        
-       timeout = jiffies+2*HZ/100;
+       timeout = jiffies+ ((2*HZ)/100);
        while (timeout >= jiffies) {
                if (rs_irq_triggered)
                        break;
@@ -2758,7+2758,9 @@ static void autoconfig(struct serial_state * state)
        if (!state->port)
                return;
        info = &scr_info;       /* This is just for serial_{in,out} */
-       info->port = state->port; 
+       info->magic = SERIAL_MAGIC;
+       info->port = state->port;
+       info->flags = state->flags;
 
        save_flags(flags); cli();
        
@@ -2848,8+2850,13 @@ static void autoconfig(struct serial_state * state)
                serial_outp(info, UART_FCR,
                            UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
                scratch = serial_in(info, UART_IIR) >> 5;
-               if (scratch == 7)
-                       state->type = PORT_16750;
+               if (scratch == 7) {
+                       serial_outp(info, UART_LCR, 0);
+                       serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+                       scratch = serial_in(info, UART_IIR) >> 5;
+                       if (scratch == 7)
+                               state->type = PORT_16750;
+               }
                serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
        }
        serial_outp(info, UART_LCR, scratch2);
diff --git a/drivers/isdn/teles/proto.h b/drivers/isdn/teles/proto.h
new file mode 100644 (file)
index 0000000..0d7ae8e
--- /dev/null
@@ -0,0 +1,18 @@
+/* $Id: proto.h,v 1.1 1996/09/23 01:53:52 fritz Exp $
+ *
+ * not much now - just the l3 proto discriminator
+ *
+ * $Log: proto.h,v $
+ * Revision 1.1  1996/09/23 01:53:52  fritz
+ * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6).
+ *
+ */
+
+#ifndef        PROTO_H
+#define        PROTO_H
+
+#define        PROTO_EURO              0x08
+#define        PROTO_DIS_N0    0x40
+#define        PROTO_DIS_N1    0x41
+
+#endif
index 7eb8adb..cb88e4d 100644 (file)
 static char *version =
 "tulip.c:v0.10 8/11/95 becker@cesdis.gsfc.nasa.gov\n"
 "        +0.72 4/17/96 "
-"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n";
+"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n"
+"        +0.01 10/24/96 mjacob@feral.com (2.1.7)\n";
 
 /* A few user-configurable values. */
 
@@ -334,6+335,7 @@ struct tulip_private {
        int setup_frame[48];    /* Pseudo-Tx frame to init address table. */
        void (*port_select)(struct device *dev);
        int (*port_fail)(struct device *dev);
+       struct device *next_module;
        char *signature;
        unsigned int cur_rx, cur_tx;            /* The next free ring entry */
        unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
@@ -367,7+369,6 @@ static int tulip_rx(struct device *dev);
 static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int tulip_close(struct device *dev);
 static struct enet_statistics *tulip_get_stats(struct device *dev);
-static struct device *tulip_alloc(struct device *dev);
 static void set_multicast_list(struct device *dev);
 
 #define        generic21140_fail       NULL
@@ -379,6+380,11 @@ static void cogent21140_select(struct device *dev);
 static int generic21040_fail(struct device *dev);
 static int generic21041_fail(struct device *dev);
 
+#ifdef MODULE
+/* A list of all installed Tulip devices, for removing the driver module. */
+static struct device *root_tulip_dev = NULL;
+#endif
+
 static struct {
        void (*port_select)(struct device *dev);
        int (*port_fail)(struct device *dev);
@@ -436,7+442,6 @@ static struct {
 
 #ifdef MODULE
 static int if_port=TULIP_AUTO_PORT;
-static size_t alloc_size;
 #ifdef TULIP_FULL_DUPLEX
 static int full_duplex=1;
 #else
@@ -1132,6+1137,7 @@ static void set_multicast_list(struct device *dev)
                        *setup_frm++ = eaddrs[2];
                } while (++i < 15);
 
+#ifndef        __alpha__
                /* Now add this frame to the Tx list. */
                {
                        unsigned long flags;
@@ -1152,46+1158,8 @@ static void set_multicast_list(struct device *dev)
                        /* Trigger an immediate transmit demand. */
                        tio_write(TPOLL_TRIGGER, CSR1);
                }
-       }
-}
-
-static struct device *tulip_alloc(struct device *dev)
-{
-       struct tulip_private *tp;
-       char *buff;
-#ifndef        MODULE
-       size_t alloc_size;
 #endif
-       if (!dev || dev->priv) {
-               struct device *olddev = dev;
-
-               alloc_size = sizeof(struct device)
-                       + sizeof(struct tulip_private)
-                       + ETHNAMSIZ;
-               alloc_size = ROUND_UP(alloc_size, 8);
-
-               buff = (char *)kmalloc(alloc_size, GFP_KERNEL);
-               dev = (struct device *)buff;
-               if (dev == NULL) {
-                       printk("tulip_alloc: kmalloc failed.\n");
-                       return(NULL);
-               }
-               tp = (struct tulip_private *)(buff + sizeof(struct device));
-               memset(buff, 0, alloc_size);
-               dev->priv = (void *)tp;
-               dev->name = (char *)(buff + sizeof(struct device)
-                                                        + sizeof(struct tulip_private));
-               if (olddev) {
-                       dev->next = olddev->next;
-                       olddev->next = dev;
-               }
-       } else {
-               alloc_size = ROUND_UP(sizeof(struct tulip_private), 8);
-               tp = (struct tulip_private *)kmalloc(alloc_size, GFP_KERNEL);
-               memset((void *)tp, 0, alloc_size);
-               dev->priv = (void *)tp;
        }
-       return(dev);
 }
 
 int
@@ -1200,6+1168,7 @@ tulip_hwinit(struct device *dev, int ioaddr,
 {
        /* See note below on the Znyx 315 etherarray. */
        static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+       static int last_irq;
        char detect_mesg[80], *mesgp=detect_mesg;
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
        int i;
@@ -1269,11+1238,13 @@ tulip_hwinit(struct device *dev, int ioaddr,
                for (i = 0; i < ETH_ALEN - 1; i++)
                        dev->dev_addr[i] = last_phys_addr[i];
                dev->dev_addr[i] = last_phys_addr[i] + 1;
+               irq = last_irq;
        }
        for (i = 0; i < ETH_ALEN - 1; i++)
                mesgp += sprintf(mesgp, "%2.2x:", dev->dev_addr[i]);
        mesgp += sprintf(mesgp, "%2.2x, IRQ %d\n",
                                         last_phys_addr[i] = dev->dev_addr[i], irq);
+       last_irq = irq;
 
        /* copy ethernet address */
        if (card_type(tp, device_id,
@@ -1295,21+1266,20 @@ tulip_hwinit(struct device *dev, int ioaddr,
        dev->set_multicast_list = &set_multicast_list;
 
 #ifdef MODULE
-    ether_setup(dev);
        if (if_port == TULIP_AUTO_PORT)
                if_port = TULIP_PORT;
        else
                tp->port_fix = 1;
        dev->if_port = if_port;
        tp->full_duplex = full_duplex;
+       tp->next_module = root_tulip_dev;
+       root_tulip_dev = dev;
 #else
 #ifdef TULIP_FULL_DUPLEX
        tp->full_duplex = 1;
 #endif
-    init_etherdev(dev, 0);
        dev->if_port = TULIP_PORT;
 #endif
-
 #ifdef TULIP_FIX_PORT
        tp->port_fix = 1;
 #endif
@@ -1340,14+1310,13 @@ int tulip_probe(struct device *dev)
 
     if (!pcibios_present()) return(-ENODEV);
 
-       for (pci_index = 0; pci_index < 8; pci_index++) {
+       for (pci_index = 0; pci_index < 0xff; pci_index++) {
                /* Search for the PCI_DEVICE_ID_DEV_TULIP* chips */
-               for (cno = 0; pci_chips[cno] != PCI_DEVICE_ID_NONE; cno ++)
+               for (cno = 0; pci_chips[cno] != PCI_DEVICE_ID_NONE; cno++) {
                        if (pcibios_find_device(PCI_VENDOR_ID_DEC,
                                                                        pci_chips[cno],
                                                                        pci_index, &pci_bus,
                                                                        &pci_device_fn) == 0) {
-                               struct device *dp;
 
                                /* get IO address */
                                pcibios_read_config_dword(pci_bus, pci_device_fn,
@@ -1355,19+1324,14 @@ int tulip_probe(struct device *dev)
                                                                                  &pci_ioaddr);
                                /* Remove I/O space marker in bit 0. */
                                pci_ioaddr &= ~3;
-                               for (dp = tulip_head; dp != NULL; dp = dp->next)
-                                       if (dp->base_addr == pci_ioaddr) break;
-                               if (dp) continue;
                                /* get IRQ */
-                               pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                                PCI_INTERRUPT_LINE, &pci_irq);
-#ifdef MODULE
-                               /* compare requested IRQ/IO address */
-                               if (dev && dev->base_addr &&
-                                       dev->base_addr != pci_ioaddr) continue;
-#else
-                               if ((dev = tulip_alloc(dev)) == NULL) break;
-#endif
+                               pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq);
+                               dev = init_etherdev(NULL, 
+                                       ROUND_UP(sizeof(struct device) +
+                                               sizeof (struct tulip_private) +
+                                               ETHNAMSIZ, 8));
+
+                               if (dev == NULL) break;
                                if (!tulip_head) {
                                        printk(version);
                                        tulip_head = dev;
@@ -1394,56+1358,48 @@ int tulip_probe(struct device *dev)
                                                                                          PCI_LATENCY_TIMER, 100);
                                }
                                if (tulip_hwinit(dev, pci_ioaddr, pci_irq,
-                                                                pci_chips[cno]) < 0) continue;
-                               num ++;
-#ifdef MODULE
-                               return(0);
-#endif
+                                                                pci_chips[cno]) < 0) {
+                                       continue;
+                               }
+                               num++;
 #ifdef TULIP_MAX_CARDS
                                if (num >= TULIP_MAX_CARDS) return(0);
 #endif
                }
        }
+       }
        return(num > 0 ? 0: -ENODEV);
 }
 
 #ifdef MODULE
-#ifdef __alpha__
-#if 1
-static int io = 0xb000;
-#else
-static int io = 0x10400;
-#endif
-#else
-static int io = 0xfc80;
-#endif
 
-static struct device *mod_dev;
+/* The parameters that may be passed in... */
+/* This driver does nothing with options yet.  It will later be used to
+   pass the full-duplex flag, etc. */
+int debug = -1;
 
-int init_module(void)
+int
+init_module(void)
 {
-       if ((mod_dev = tulip_alloc(0)) == NULL) return(-EIO);
-
-       mod_dev->base_addr = io;
-       mod_dev->irq = 0;
-       mod_dev->init = &tulip_probe;
-
-       if (register_netdev(mod_dev)) {
-               printk("tulip: register_netdev() returned non-zero.\n");
-               kfree_s(mod_dev, alloc_size);
-               return -EIO;
-       }
-       return(0);
+       root_tulip_dev = NULL;
+       return tulip_probe(NULL);
 }
 
 void
 cleanup_module(void)
 {
-       release_region(mod_dev->base_addr, TULIP_TOTAL_SIZE);
-       unregister_netdev(mod_dev);
-       kfree_s(mod_dev, alloc_size);
+       struct device *next_dev;
+
+       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+       while (root_tulip_dev) {
+               next_dev =
+                  ((struct tulip_private *) root_tulip_dev->priv)->next_module;
+               unregister_netdev(root_tulip_dev);
+               release_region(root_tulip_dev->base_addr, TULIP_TOTAL_SIZE);
+               kfree(root_tulip_dev);
+               root_tulip_dev = next_dev;
+       }
 }
-
 #endif /* MODULE */
 
 \f
index 48f91cd..fba1ef2 100644 (file)
@@ -3,6+3,9 @@ comment 'SCSI support type (disk, tape, CD-ROM)'
 dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
 dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
 dep_tristate 'SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
+  bool '  Enable vendor-specific extentions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+fi
 dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
 
 comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
index c1f3cf4..0b5489b 100644 (file)
@@ -58,8+58,12 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_BLK_DEV_SR_VENDOR),y)
+SR_VENDOR = sr_vendor.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_SR),y)
-L_OBJS += sr.o sr_ioctl.o
+L_OBJS += sr.o sr_ioctl.o $(SR_VENDOR)
 else
   ifeq ($(CONFIG_BLK_DEV_SR),m)
   M_OBJS += sr_mod.o
@@ -376,8+380,8 @@ scsi_mod.o: $(MX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \
                scsicam.o scsi_proc.o
        $(LD) $(LD_RFLAG) -r -o $@ $(MX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o
 
-sr_mod.o: sr.o sr_ioctl.o
-       $(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o
+sr_mod.o: sr.o sr_ioctl.o $(SR_VENDOR)
+       $(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o $(SR_VENDOR)
 
 sd_mod.o: sd.o sd_ioctl.o
        $(LD) $(LD_RFLAG) -r -o $@ sd.o sd_ioctl.o
index 6c9b7e0..3659d6a 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: advansys.c,v 1.24 1996/10/05 00:58:14 bobf Exp bobf $ */
+/* $Id: advansys.c,v 1.29 1996/11/15 00:45:07 bobf Exp bobf $ */
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  * 
 
 /*
  * The driver has been used in the following kernels:
- * v1.2.13, v1.3.57, v2.0.21, v2.1.0
+ *  v1.2.13, v1.3.57, v2.0.25, v2.1.9
  */
-#define ASC_VERSION "1.8"    /* AdvanSys Driver Version */
+#define ASC_VERSION "2.0"    /* AdvanSys Driver Version */
 
 /*
 
 
      Connectivity Products:
         ABP510/5150 - Bus-Master ISA (240 CDB) (Footnote 1)
-        ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1)
-        ABP5142 - Bus-Master ISA PnP with floppy (16 CDB)
+        ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1, 3)
+        ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) (Footnote 4)
         ABP920 - Bus-Master PCI (16 CDB)
-        ABP930 - Bus-Master PCI (16 CDB)
+        ABP930 - Bus-Master PCI (16 CDB) (Footnote 5)
         ABP930U - Bus-Master PCI Ultra (16 CDB)
         ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2)
         ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
        1. This board has been shipped by HP with the 4020i CD-R drive.
           The board has no BIOS so it cannot control a boot device, but
           it can control any secondary SCSI device.
-   
        2. This board has been sold by Iomega as a Jaz Jet PCI adapter.
-  
+       3. This board has been sold by SIIG as the i540 SpeedMaster.
+       4. This board has been sold by SIIG as the i542 SpeedMaster.
+       5. This board has been sold by SIIG as the Fast SCSI Pro PCI.
+
   B. Linux v1.2.X - Directions for Adding the AdvanSys Driver
 
      These directions apply to v1.2.13. For versions that follow v1.2.13.
          5. Add request response time statistics and other information to
             the adapter /proc file: /proc/scsi/advansys[0...].
 
+     1.9 (10/21/96):
+         1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
+            make use of mid-level SCSI driver device queue depth flow
+            control mechanism. This will eliminate aborts caused by a
+            device being unable to keep up with requests and eliminate
+            repeat busy or QUEUE FULL status returned by a device.
+         2. Incorporate miscellaneous Asc Library bug fixes.
+         3. To allow the driver to work in kernels with broken module
+            support set 'cmd_per_lun' if the driver is compile as a
+            module. This change affects kernels v1.3.89 to present.
+         4. Remove PCI BIOS address from the driver banner. The PCI BIOS
+            is relocated by the motherboard BIOS and its new address can
+            not be determined by the driver.
+         5. Add mid-level SCSI queue depth information to the adapter
+            /proc file: /proc/scsi/advansys[0...].
+
+     2.0 (11/14/96):
+         1. Change allocation of global structures used for device
+            initialization to guarantee they are in DMA-able memory.
+            Previously when the driver was loaded as a module these
+            structures might not have been in DMA-able memory, causing
+            device initialization to fail.
+
   I. Known Problems or Issues
 
-         1. If a large "Device Queue Size" is set in the adapter
-            BIOS and a device supports the queue depth and the device
-            is heavily loaded, requests may be sent to the device
-            faster than they can be executed causing the requests to
-            queue up in the low-level driver on a wait queue. This may
-            lead to time-out abort requests by the mid-level driver.
-            
-            The short term solution is to set a smaller "Device Queue
-            Size" in the adapter BIOS. Response times can be monitored
-            per device by reading the /proc/scsi/advansys/[0...] file.
-            
-            The long term solution is to modify the mid-level driver to
-            institute a flow control mechanism between the two levels.
-            The low-level driver would notify the mid-level driver when
-            a device is falling behind on executing requests. This would
-            prevent the mid-level driver from sending more requests until
-            the low-level driver has notified it that the device has caught
-            up on request execution.
+         1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around
+            the queue depth flow control code when mid-level SCSI changes
+            are included in Linux.
 
   J. Credits
 
 
 #define ASC_LIB_VERSION_MAJOR  1
 #define ASC_LIB_VERSION_MINOR  22
-#define ASC_LIB_SERIAL_NUMBER  89
+#define ASC_LIB_SERIAL_NUMBER  91
 
 typedef unsigned char uchar;
 
@@ -645,7+655,6 @@ typedef unsigned char uchar;
 #define ASC_PCI_ID2FUNC( id )   (((id) >> 8) & 0x7)
 #define ASC_PCI_MKID( bus, dev, func ) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
 
-#define  Asc_DvcLib_Status   int
 #define  ASC_DVCLIB_CALL_DONE     (1)
 #define  ASC_DVCLIB_CALL_FAILED   (0)
 #define  ASC_DVCLIB_CALL_ERROR    (-1)
@@ -853,7+862,7 @@ AscMemWordCopyToLram(iop_base, s_addr, outbuf, words)
 #define SCSI_SENKEY_MEDIUM_ERR    0x03
 #define SCSI_SENKEY_HW_ERR        0x04
 #define SCSI_SENKEY_ILLEGAL       0x05
-#define SCSI_SENKEY_ATTENSION     0x06
+#define SCSI_SENKEY_ATTENTION     0x06
 #define SCSI_SENKEY_PROTECTED     0x07
 #define SCSI_SENKEY_BLANK         0x08
 #define SCSI_SENKEY_V_UNIQUE      0x09
@@ -1379,7+1388,6 @@ typedef struct asc_risc_sg_list_q {
 #define ASC_IERR_SCAM                 0x0800
 #define ASC_IERR_SET_SDTR             0x1000
 #define ASC_IERR_RW_LRAM              0x8000
-#define ASC_DVCLIB_STATUS             0x00
 #define ASC_DEF_IRQ_NO  10
 #define ASC_MAX_IRQ_NO  15
 #define ASC_MIN_IRQ_NO  10
@@ -2138,7+2146,7 @@ int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SA
 #define ASC_INFO_SIZE                  128                     /* advansys_info() line size */
 
 /* /proc/scsi/advansys/[0...] related definitions */
-#define ASC_PRTBUF_SIZE                        1024
+#define ASC_PRTBUF_SIZE                        2048
 #define ASC_PRTLINE_SIZE               160
 
 #define ASC_PRT_NEXT() \
@@ -2310,7+2318,11 @@ typedef Scsi_Cmnd                        REQ, *REQP;
 #endif /* ADVANSYS_STATS */
 
 #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
-#define ASC_TENTHS(num, den) ((((num) * 10)/(den)) - (10 * ((num)/(den))))
+
+/* If the result wraps when calculating tenths, return 0. */
+#define ASC_TENTHS(num, den) \
+       (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
+       0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
 
 /*
  * Display a message to the console.
@@ -2490,9+2502,6 @@ struct asc_stats {
        ulong   sg_cnt;                 /* # scatter-gather I/O requests received */
        ulong   sg_elem;                /* # scatter-gather elements */
        ulong   sg_xfer;                /* # scatter-gather transfer 512-bytes */
-       /* Device SCSI Command Queuing Statistics */
-       ASC_SCSI_BIT_ID_TYPE queue_full;
-       ushort  queue_full_cnt[ASC_MAX_TID+1];
 };
 #endif /* ADVANSYS_STATS */
 
@@ -2529,9+2538,19 @@ typedef struct asc_board {
        asc_queue_t                      waiting;                       /* Waiting command queue */
        asc_queue_t                      done;                          /* Done command queue */
        ASC_SCSI_BIT_ID_TYPE init_tidmask;              /* Target initialized mask */
+       /* The following three structures must be in DMA-able memory. */
+       ASC_SCSI_REQ_Q           scsireqq;
+       ASC_CAP_INFO             cap_info;
+       ASC_SCSI_INQUIRY         inquiry;
+       Scsi_Device                      *device[ASC_MAX_TID+1]; /* Mid-Level Scsi Device */
+       ushort                           reqcnt[ASC_MAX_TID+1]; /* Starvation request count */
+#if ASC_QUEUE_FLOW_CONTROL
+       ushort                           nerrcnt[ASC_MAX_TID+1]; /* No error request count */
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+       ASC_SCSI_BIT_ID_TYPE queue_full;                /* Queue full mask */
+       ushort  queue_full_cnt[ASC_MAX_TID+1];  /* Queue full count */
        ASCEEP_CONFIG            eep_config;            /* EEPROM configuration */
        ulong                            last_reset;            /* Saved time of last reset */
-       ushort                           rcnt[ASC_MAX_TID+1]; /* Starvation Request Count */
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
        /* /proc/scsi/advansys/[0...] */
        char                             *prtbuf;                       /* Statistics Print Buffer */
@@ -2616,13+2635,6 @@ STATIC struct Scsi_Host  *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
 STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
 
 /*
- * Global structures used for device initialization.
- */
-STATIC ASC_SCSI_REQ_Q   asc_scsireqq = { { 0 } };
-STATIC ASC_CAP_INFO             asc_cap_info = { 0 };
-STATIC ASC_SCSI_INQUIRY         asc_inquiry = { { 0 } };
-
-/*
  * Global structures required to issue a command.
  */
 STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
@@ -3124,6+3136,7 @@ advansys_detect(Scsi_Host_Template *tpnt)
                        memset(boardp, 0, sizeof(asc_board_t));
                        boardp->id = asc_board_count - 1;
                        asc_dvc_varp = &boardp->asc_dvc_var;
+                       asc_dvc_varp->drv_ptr = (ulong) boardp;
                        asc_dvc_varp->cfg = &boardp->asc_dvc_cfg;
                        asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
                        asc_dvc_varp->iop_base = iop;
@@ -3179,9+3192,9 @@ advansys_detect(Scsi_Host_Template *tpnt)
                        /*
                         * Get the board configuration.
                         *
-                        * AscInitGetConfig() may change the board's bus_type value.
-                        * The asc_bus[bus] value should no longer be used. If the
-                        * bus_type field must be referenced only use the bit-wise
+                        * NOTE: AscInitGetConfig() may change the board's bus_type
+                        * value. The asc_bus[bus] value should no longer be used. If
+                        * the bus_type field must be referenced only use the bit-wise
                         * AND operator "&".
                         */
                        ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
@@ -3312,7+3325,7 @@ advansys_detect(Scsi_Host_Template *tpnt)
                         */
 
                        /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
-                       if (asc_dvc_varp->bus_type != ASC_IS_PCI) {
+                       if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
                                shp->irq = asc_dvc_varp->irq_no;
                        }
 
@@ -3351,16+3364,33 @@ advansys_detect(Scsi_Host_Template *tpnt)
                         */
                        shp->select_queue_depths = advansys_select_queue_depths;
 
-                       shp->cmd_per_lun = 0; /* 'cmd_per_lun' is no longer used. */
+#ifdef MODULE
+                       /*
+                        * Following v1.3.89, 'cmd_per_lun' is no longer needed
+                        * and should be set to zero. But because of a bug introduced
+                        * in v1.3.89 if the driver is compiled as a module and
+                        * 'cmd_per_lun' is zero, the Mid-Level SCSI function
+                        * 'allocate_device' will panic. To allow the driver to
+                        * work as a module in these kernels set 'cmd_per_lun' to 1.
+                        */
+                       shp->cmd_per_lun = 1;
+#else /* MODULE */
+                       shp->cmd_per_lun = 0;
+#endif /* MODULE */
 #endif /* version >= v1.3.89 */
 
                        /*
-                        * Maximum number of scatter-gather elements adapter can handle.
-                        *
-                        * Set a conservative 'sg_tablesize' value to prevent memory
-                        * allocation failures.
+                        * Set the maximum number of scatter-gather elements adapter
+                        * can handle.
                         */
+
 #ifdef MODULE
+                       /*
+                        * If the driver is compiled as a module, set a conservative
+                        * 'sg_tablesize' value to prevent memory allocation failures.
+                        * Memory allocation errors are more likely to occur at module
+                        * load time, then at driver initialization time.
+                        */
                        shp->sg_tablesize = 8;
 #else /* MODULE */
                        /*
@@ -3539,25+3569,28 @@ advansys_info(struct Scsi_Host *shp)
                        ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
                        (unsigned) shp->base, shp->io_port,
                        shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
+       } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
+               if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
+                       == ASC_IS_PCI_ULTRA) {
+                       busname = "PCI Ultra";
+               } else {
+                       busname = "PCI";
+               }
+               sprintf(info,
+                       "AdvanSys SCSI %s: %s %u CDB: IO %X-%X, IRQ %u",
+                       ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
+                       shp->io_port, shp->io_port + (shp->n_io_port - 1), shp->irq);
        } else {
                if (asc_dvc_varp->bus_type & ASC_IS_VL) {
                        busname = "VL";
                } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
                        busname = "EISA";
-               } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
-                       if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
-                               == ASC_IS_PCI_ULTRA) {
-                               busname = "PCI Ultra";
-                       } else {
-                               busname = "PCI";
-                       }
                } else {
                        busname = "?";
                        ASC_PRINT2(
 "advansys_info: board %d: unknown bus type %d\n",
                                boardp->id, asc_dvc_varp->bus_type);
                }
-               /* No DMA channel for non-ISA busses. */
                sprintf(info,
                        "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X-%X, IRQ %u",
                        ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
@@ -4429,6+4462,11 @@ advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
                if (device->host != shp) {
                        continue;
                }
+               /*
+                * Save a pointer to the device and set its initial/maximum
+                * queue depth.
+                */
+               boardp->device[device->id] = device;
                device->queue_depth = boardp->asc_dvc_var.max_dvc_qng[device->id];
                ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
                        (unsigned) shp, device->id, device->queue_depth);
@@ -4516,6+4554,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 {
        asc_board_t             *boardp;
        ASC_DVC_VAR             *asc_dvc_varp;
+       Scsi_Device             *device;
        int                             ret;
 
        ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
@@ -4524,6+4563,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 
        boardp = ASC_BOARDP(scp->host);
        asc_dvc_varp = &boardp->asc_dvc_var;
+       device = boardp->device[scp->target];
 
        /*
         * If this is the first command, then initialize the device. If
@@ -4557,25+4597,26 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
        asc_scsi_q.q1.target_lun = scp->lun;
        asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
        asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
-#else /* version >= v2.1.0 */
+#else /* version >= v2.0.0 */
        asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
-#endif /* version >= v2.1.0 */
+#endif /* version >= v2.0.0 */
        asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
 
        /*
-        * If there are more than five outstanding commands for the
-        * current target, then every tenth command send an ORDERED
-        * request. This heuristic tries to retain the benefit of
-        * request sorting while preventing request starvation.
+        * If there are any outstanding requests for the current target,
+        * then every 255th request send an ORDERED request. This heuristic
+        * tries to retain the benefit of request sorting while preventing
+        * request starvation. 255 is the max number of tags or pending commands
+        * a device may have outstanding.
         *
         * The request count is incremented below for every successfully
         * started request.
         * 
         */
-       if ((asc_dvc_varp->cur_dvc_qng[scp->target] > 5) &&
-           (boardp->rcnt[scp->target] % 10) == 0) {
+       if ((asc_dvc_varp->cur_dvc_qng[scp->target] > 0) &&
+           (boardp->reqcnt[scp->target] % 255) == 0) {
                asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
        } else {
                asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
@@ -4590,11+4631,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                 * CDB request of single contiguous buffer.
                 */
                ASC_STATS(scp->host, cont_cnt);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
                asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
-#else /* version >= v2.1.0 */
+#else /* version >= v2.0.0 */
                asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
-#endif /* version >= v2.1.0 */
+#endif /* version >= v2.0.0 */
                asc_scsi_q.q1.data_cnt = scp->request_bufflen;
                ASC_STATS_ADD(scp->host, cont_xfer,
                                          ASC_CEILING(scp->request_bufflen, 512));
@@ -4636,11+4677,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                 */
                slp = (struct scatterlist *) scp->request_buffer;
                for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
                        asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
-#else /* version >= v2.1.0 */
+#else /* version >= v2.0.0 */
                        asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
-#endif /* version >= v2.1.0 */
+#endif /* version >= v2.0.0 */
                        asc_sg_head.sg_list[sgcnt].bytes = slp->length;
                        ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
                }
@@ -4658,21+4699,55 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                ASC_STATS(scp->host, asc_noerror);
                /*
                 * Increment monotonically increasing per device successful
-                * request count. Wrapping of 'rcnt' doesn't matter.
+                * request counter. Wrapping doesn't matter.
+                */
+               boardp->reqcnt[scp->target]++;
+
+#if ASC_QUEUE_FLOW_CONTROL
+               /*
+                * Conditionally increment the device queue depth.
+                *
+                * If no error occurred and there have been 100 consecutive
+                * successfull requests and the current queue depth is less
+                * than the maximum queue depth, then increment the current
+                * queue depth.
                 */
-               boardp->rcnt[scp->target]++;
+               if (boardp->nerrcnt[scp->target]++ > 100) {
+                       boardp->nerrcnt[scp->target] = 0;
+                       if ((device->queue_curr_depth < device->queue_depth) &&
+                           (!(boardp->queue_full & ASC_TIX_TO_TARGET_ID(scp->target)) ||
+                                (boardp->queue_full_cnt[scp->target] >
+                                 device->queue_curr_depth))) {
+                               device->queue_curr_depth++;
+                       }
+               }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                asc_enqueue(&boardp->active, scp, ASC_BACK);
                ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
                break;
        case ASC_BUSY:
                /* Caller must enqueue request and retry later. */
                ASC_STATS(scp->host, asc_busy);
+#if ASC_QUEUE_FLOW_CONTROL
+               /*
+                * Clear consecutive no error counter and if possbile decrement
+                * queue depth.
+                */
+               boardp->nerrcnt[scp->target] = 0;
+               if (device->queue_curr_depth > 1) {
+                       device->queue_curr_depth--;
+               }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                break;
        case ASC_ERROR:
                ASC_PRINT2(
 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
                        boardp->id, asc_dvc_varp->err_code);
                ASC_STATS(scp->host, asc_error);
+#if ASC_QUEUE_FLOW_CONTROL
+               /* Clear consecutive no error counter. */
+               boardp->nerrcnt[scp->target] = 0;
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                scp->result = HOST_BYTE(DID_ERROR);
                asc_enqueue(&boardp->done, scp, ASC_BACK);
                break;
@@ -4681,6+4756,10 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
                        boardp->id, asc_dvc_varp->err_code);
                ASC_STATS(scp->host, asc_unknown);
+#if ASC_QUEUE_FLOW_CONTROL
+               /* Clear consecutive no error counter. */
+               boardp->nerrcnt[scp->target] = 0;
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                scp->result = HOST_BYTE(DID_ERROR);
                asc_enqueue(&boardp->done, scp, ASC_BACK);
                break;
@@ -4836,6+4915,9 @@ STATIC int
 asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
 {
        asc_board_t                             *boardp;
+       ASC_SCSI_REQ_Q                  *scsireqq;
+       ASC_CAP_INFO                    *cap_info;
+       ASC_SCSI_INQUIRY                *inquiry;
        int                                             found;
        ASC_SCSI_BIT_ID_TYPE    save_use_tagged_qng;
        ASC_SCSI_BIT_ID_TYPE    save_can_tagged_qng;
@@ -4852,9+4934,11 @@ asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
        boardp = ASC_BOARDP(scp->host);
 
        /* Set-up AscInitPollTarget() arguments. */
-       memset(&asc_scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
-       memset(&asc_cap_info, 0, sizeof(ASC_CAP_INFO));
-       memset(&asc_inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
+       scsireqq = &boardp->scsireqq;
+       memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
+       cap_info = &boardp->cap_info;
+       memset(cap_info, 0, sizeof(ASC_CAP_INFO));
+       inquiry = &boardp->inquiry;
 
        /*
         * XXX - AscInitPollBegin() re-initializes these fields to
@@ -4872,24+4956,24 @@ asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
                return ASC_FALSE;
        }
 
-       asc_scsireqq.sense_ptr = &asc_scsireqq.sense[0];
-       asc_scsireqq.r1.sense_len = ASC_MIN_SENSE_LEN;
-       asc_scsireqq.r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
-       asc_scsireqq.r1.target_lun = 0;
-       asc_scsireqq.r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
+       scsireqq->sense_ptr = &scsireqq->sense[0];
+       scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
+       scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+       scsireqq->r1.target_lun = 0;
+       scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
 
        found = ASC_FALSE;
        ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
-       switch (ret = AscInitPollTarget(asc_dvc_varp, &asc_scsireqq,
-               &asc_inquiry, &asc_cap_info)) {
+       switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry,
+               cap_info)) {
        case ASC_TRUE:
                found = ASC_TRUE;
 #ifdef ADVANSYS_DEBUG
                tidmask = ASC_TIX_TO_TARGET_ID(scp->target);
                ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
-                       asc_cap_info.lba, asc_cap_info.blk_size);
+                       cap_info->lba, cap_info->blk_size);
                ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
-                       asc_inquiry.byte0.peri_dvc_type);
+                       inquiry->byte0.peri_dvc_type);
                if (asc_dvc_varp->use_tagged_qng & tidmask) {
                        ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
                                asc_dvc_varp->max_dvc_qng[scp->target]);
@@ -5677,7+5761,7 @@ asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if (boardp->asc_dvc_cfg.chip_scsi_id == i) {
                        continue;
-               } else if (boardp->init_tidmask & (1 << i)) {
+               } else if (boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
                        len = asc_prt_line(cp, leftlen, " %d,", i);
                        ASC_PRT_NEXT();
                }
@@ -5733,7+5817,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->disc_enable & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->disc_enable & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5744,7+5828,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->use_cmd_qng & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->use_cmd_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5755,7+5839,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->start_motor & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->start_motor & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5766,7+5850,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->init_sdtr & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->init_sdtr & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5794,9+5878,15 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
 STATIC int
 asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
 {
+       asc_board_t                     *boardp;
        int                                     leftlen;
        int                                     totlen;
        int                                     len;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+       int                                     i;
+#endif /* version >= v1.3.89 */
+
+       boardp = ASC_BOARDP(shp);
 
        leftlen = cplen;
        totlen = len = 0;
@@ -5843,6+5933,55 @@ asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
                ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->last_reset, jiffies);
        ASC_PRT_NEXT();
 
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+       len = asc_prt_line(cp, leftlen,
+" queue_depth:     ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %d:%d",
+                       i, boardp->device[i]->queue_depth);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
+#endif /* version >= v1.3.89 */
+
+#if ASC_QUEUE_FLOW_CONTROL
+       len = asc_prt_line(cp, leftlen,
+" queue_curr_depth:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %d:%d",
+                       i, boardp->device[i]->queue_curr_depth);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
+
+       len = asc_prt_line(cp, leftlen,
+" queue_count:     ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %d:%d",
+                       i, boardp->device[i]->queue_count);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+
        return totlen;
 }
 
@@ -5867,9+6006,6 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_DVC_VAR                     *v;
        ASC_DVC_CFG                     *c;
        int                                     i;
-#ifdef ADVANSYS_STATS
-       struct asc_stats        *s;
-#endif /* ADVANSYS_STATS */
 
        boardp = ASC_BOARDP(shp);
        v = &boardp->asc_dvc_var;
@@ -5903,11+6039,11 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (v->sdtr_done & (1 << i)) ? 'Y' : 'N');
+                       i, (v->sdtr_done & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5918,11+6054,11 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (v->use_tagged_qng & (1 << i)) ? 'Y' : 'N');
+                       i, (v->use_tagged_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5934,7+6070,7 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
@@ -5949,7+6085,7 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
@@ -5958,21+6094,18 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        len = asc_prt_line(cp, leftlen, "\n");
        ASC_PRT_NEXT();
 
-#ifdef ADVANSYS_STATS
-       s = &boardp->asc_stats;
-
        /* Indicate whether the device has returned queue full status. */
        len = asc_prt_line(cp, leftlen,
 " Command Queue Full:      ");
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
-               if (s->queue_full & (1 << i)) {
+               if (boardp->queue_full & ASC_TIX_TO_TARGET_ID(i)) {
                        len = asc_prt_line(cp, leftlen, " %d:Y-%d",
-                               i, s->queue_full_cnt[i]);
+                               i, boardp->queue_full_cnt[i]);
                } else {
                        len = asc_prt_line(cp, leftlen, " %d:N", i);
                }
@@ -5980,7+6113,6 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        }
        len = asc_prt_line(cp, leftlen, "\n");
        ASC_PRT_NEXT();
-#endif /* ADVANSYS_STATS */
 
        return totlen;
 }
@@ -6103,11+6235,11 @@ DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
 {
        ulong bus_addr;
 
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
        bus_addr = (ulong) buf_addr;
-#else /* version >= v2.1.0 */
+#else /* version >= v2.0.0 */
        bus_addr = virt_to_bus(buf_addr);
-#endif /* version >= v2.1.0 */
+#endif /* version >= v2.0.0 */
        return bus_addr;
 }
 
@@ -6119,11+6251,11 @@ DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
 
        buf_size = buf_len;
        asc_sg_head_ptr->entry_cnt = 1;
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
        asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
-#else /* version >= v2.1.0 */
+#else /* version >= v2.0.0 */
        asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
-#endif /* version >= v2.1.0 */
+#endif /* version >= v2.0.0 */
        asc_sg_head_ptr->sg_list[0].bytes = buf_size;
        return buf_size;
 }
@@ -6280,8+6412,6 @@ DvcWritePCIConfigByte(
 /*
  * Return the BIOS address of the adapter at the specified
  * I/O port and with the specified bus type.
- *
- * This function was formerly supplied by the library.
  */
 ushort
 AscGetChipBiosAddress(
@@ -6292,13+6422,15 @@ AscGetChipBiosAddress(
     ushort  cfg_lsw ;
     ushort  bios_addr ;
 
-    /*
-     *   We can't get the BIOS address for PCI
-     */
-    if ( bus_type & ASC_IS_PCI )
-    {
-        return( 0 );
-    }
+       /*
+        * The PCI BIOS is re-located by the motherboard BIOS. Because
+        * of this the driver can not determine where a PCI BIOS is
+        * loaded and executes.
+        */
+       if ( bus_type & ASC_IS_PCI )
+       {
+               return( 0 );
+       }
 
     if( ( bus_type & ASC_IS_EISA ) != 0 )
     {
@@ -7173,6+7305,8 @@ AscIsrChipHalted(
                                                asc_dvc->sdtr_done |= target_id;
                                                asc_dvc->init_sdtr |= target_id;
                                                asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                                               sdtr_data = AscCalSDTRData(asc_dvc,
+                                                       sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset);
                                                AscSetChipSDTR(iop_base, sdtr_data, tid_no);
                                        } else {
                                                q_cntl |= QC_MSG_OUT;
@@ -7180,6+7314,8 @@ AscIsrChipHalted(
                                                                          sdtr_xmsg.xfer_period,
                                                                          sdtr_xmsg.req_ack_offset);
                                                asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                                               sdtr_data = AscCalSDTRData(asc_dvc,
+                                                       sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset);
                                                AscSetChipSDTR(iop_base, sdtr_data, tid_no);
                                                asc_dvc->sdtr_done |= target_id;
                                                asc_dvc->init_sdtr |= target_id;
@@ -7273,24+7409,23 @@ AscIsrChipHalted(
                                                                         (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no),
                                                                         cur_dvc_qng);
                                }
-#ifdef ADVANSYS_STATS
                                {
-                                       asc_board_t             *boardp;
-                                       int                             i;
-                                       for (i = 0; i < ASC_NUM_BOARD_SUPPORTED; i++) {
-                                               if (asc_host[i] == NULL) {
-                                                       continue;
-                                               }
-                                               boardp = ASC_BOARDP(asc_host[i]);
-                                               if (&boardp->asc_dvc_var == asc_dvc) {
-                                                       boardp->asc_stats.queue_full |= target_id;
-                                                       boardp->asc_stats.queue_full_cnt[tid_no] =
-                                                         cur_dvc_qng;
-                                                       break;
-                                               }
-                                       }
+                               asc_board_t             *boardp;
+                               boardp = (asc_board_t *) asc_dvc->drv_ptr;
+
+                               /*
+                                * Set the device queue depth to the number of
+                                * active requests when the QUEUE FULL condition
+                                * was encountered.
+                                */
+                               boardp->queue_full |= target_id;
+                               boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
+#if ASC_QUEUE_FLOW_CONTROL
+                               if (boardp->device[tid_no]->queue_curr_depth > cur_dvc_qng) {
+                                       boardp->device[tid_no]->queue_curr_depth = cur_dvc_qng;
+                               }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                                }
-#endif
                        }
                }
                AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
@@ -7608,8+7743,10 @@ AscScsiSetupCmdQ(
        scsiq->r3.host_stat = 0;
        scsiq->r3.done_stat = 0;
        scsiq->r2.vm_id = 0;
-       scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
        scsiq->r1.data_cnt = buf_len;
+       scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
+       scsiq->sense_ptr = (uchar dosfar *) scsiq->sense ;
+       scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ;
        scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
        scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
        scsiq->r2.srb_ptr = (ulong) scsiq;
@@ -7622,6+7759,12 @@ AscScsiSetupCmdQ(
                }
                scsiq->r1.data_addr = phy_addr;
        }
+       if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+                       (uchar dosfar *) scsiq->sense_ptr,
+                       (ulong) scsiq->r1.sense_len )) == 0L) {
+               return (ERR);
+       }
+       scsiq->r1.sense_addr = phy_addr ;
        return (0);
 }
 
@@ -8718,21+8861,22 @@ AscGetSynPeriodIndex(
 {
        ruchar             *period_table;
        int                 max_index;
+       int                 min_index;
        int                 i;
        period_table = asc_dvc->sdtr_period_tbl;
        max_index = (int) asc_dvc->max_sdtr_index;
+       min_index = ( int )asc_dvc->host_init_sdtr_index ;
        if (
-                  (syn_time >= period_table[0])
-                  && (syn_time <= period_table[max_index])
+                  (syn_time <= period_table[max_index])
          ) {
-               for (i = 0; i < (max_index - 1); i++) {
+               for (i = min_index; i < (max_index - 1); i++) {
                        if (syn_time <= period_table[i]) {
-                               return (i);
+                               return ((uchar) i);
                        }
                }
-               return (max_index);
+               return ((uchar) max_index);
        } else {
-               return (max_index + 1);
+               return ((uchar) (max_index + 1));
        }
 }
 
@@ -9537,20+9681,20 @@ AscInitAscDvcVar(
        asc_dvc->no_scam = 0;
        asc_dvc->unit_not_ready = 0;
        asc_dvc->queue_full_or_busy = 0;
+       asc_dvc->redo_scam = 0 ;
+       asc_dvc->res2 = 0 ;
+       asc_dvc->host_init_sdtr_index = 0 ;
+       asc_dvc->res7 = 0 ;
+       asc_dvc->res8 = 0 ;
+       asc_dvc->cfg->can_tagged_qng = 0 ;
+       asc_dvc->cfg->cmd_qng_enabled = 0;
        asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
        asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET;
        asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
        asc_dvc->scsi_reset_wait = 3;
        asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
        asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
-       asc_dvc->redo_scam = 0;
-       asc_dvc->res2 = 0;
-       asc_dvc->host_init_sdtr_index = 0;
-       asc_dvc->res7 = 0;
-       asc_dvc->res8 = 0;
        asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
-       asc_dvc->cfg->can_tagged_qng = 0;
-       asc_dvc->cfg->cmd_qng_enabled = 0;
        asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
        asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
        asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
@@ -9839,6+9983,9 @@ AscInitPollIsrCallBack(
                scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
                scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
                scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
+               ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n",
+                       scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat,
+                       scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg);
                if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
                        (scsi_done_q->d3.host_stat == 0)) {
                        cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
@@ -10170,21+10317,12 @@ AscInitPollTarget(
        int                 support_read_cap;
        int                 tmp_disable_init_sdtr;
        int                 sta;
-       ulong               phy_addr;
        dvc_found = 0;
        tmp_disable_init_sdtr = FALSE;
        tid_bits = scsiq->r1.target_id;
        lun = scsiq->r1.target_lun;
        tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
        if (
-                  (phy_addr = AscGetOnePhyAddr(asc_dvc,
-                                                                               (uchar dosfar *) scsiq->sense_ptr,
-                                                                               (ulong) scsiq->r1.sense_len)) == 0L
-         ) {
-               return (ERR);
-       }
-       scsiq->r1.sense_addr = phy_addr;
-       if (
                   ((asc_dvc->init_sdtr & tid_bits) != 0)
                   && ((asc_dvc->sdtr_done & tid_bits) == 0)
          ) {
@@ -10301,7+10439,7 @@ PollQueueDone(
        int                 status;
        int                 retry = 0;
 
-       ASC_DBG1(1, "PollQueueDone: timeout_sec %d", timeout_sec);
+       ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec);
        do {
                ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n");
                if ((status = AscExeScsiQueue(asc_dvc,
@@ -10309,6+10447,7 @@ PollQueueDone(
                        ASC_DBG(1, "PollQueueDone: before AscPollQDone\n");
                        if ((status = AscPollQDone(asc_dvc, scsiq,
                                                                           timeout_sec)) != 1) {
+                               ASC_DBG1(1, "PollQueueDone: status %x\n", status);
                                if (status == 0x80) {
                                        if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
                                                break;
@@ -10324,14+10463,18 @@ PollQueueDone(
                                scsiq->r3.host_stat = 0;
                                scsiq->r3.scsi_stat = 0;
                                scsiq->r3.scsi_msg = 0;
+                               ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n");
                                AscAbortSRB(asc_dvc, (ulong) scsiq);
                        }
+                       ASC_DBG1(1, "PollQueueDone: status %x\n", status);
                        ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
                        return (scsiq->r3.done_stat);
                }
+               ASC_DBG1(1, "PollQueueDone: status %x\n", status);
                DvcSleepMilliSecond(5);
        } while (((status == 0) || (status == 0x80)) &&
                          retry++ < ASC_MAX_INIT_BUSY_RETRY);
+       ASC_DBG1(1, "PollQueueDone: status %x\n", status);
        ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n");
        return (scsiq->r3.done_stat = QD_WITH_ERROR);
 }
@@ -10430,12+10573,12 @@ InitTestUnitReady(
        ASC_REQ_SENSE dosfar *sen;
        retry = 0;
        tid_bits = scsiq->r1.target_id;
-       while (retry++ < 2) {
+       while (retry++ < 4) {
                PollScsiTestUnitReady(asc_dvc, scsiq);
                if (scsiq->r3.done_stat == 0x01) {
                        return (1);
                } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
-                       DvcSleepMilliSecond(100);
+                       DvcSleepMilliSecond(200);
                        sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr;
                        if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
                                ((sen->err_code & 0x70) != 0)) {
@@ -10451,9+10594,10 @@ InitTestUnitReady(
                                        } else {
                                                DvcSleepMilliSecond(5000);
                                        }
-                               } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) {
-                                       DvcSleepMilliSecond(500);
+                               } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) {
+                                       DvcSleepMilliSecond( ( ulong )( 500L*retry ) ) ;
                                } else {
+                                       DvcSleepMilliSecond( 500 ) ;
                                        break;
                                }
                        } else {
@@ -10485,6+10629,7 @@ AscPollQDone(
        while (TRUE) {
                if (asc_dvc->err_code != 0) {
                        scsiq->r3.done_stat = QD_WITH_ERROR;
+                       ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code);
                        sta = ERR;
                        break;
                }
@@ -10497,10+10642,12 @@ AscPollQDone(
                }
                DvcSleepMilliSecond(10);
                if (loop++ > loop_end) {
+                       ASC_DBG(1, "AscPollQDone: loop finished\n");
                        sta = 0;
                        break;
                }
                if (AscIsChipHalted(iop_base)) {
+                       ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n");
 #if !CC_ASCISR_CHECK_INT_PENDING
                        AscAckInterrupt(iop_base);
 #endif
@@ -10508,6+10655,7 @@ AscPollQDone(
                        loop = 0;
                } else {
                        if (AscIsIntPending(iop_base)) {
+                               ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n");
 #if !CC_ASCISR_CHECK_INT_PENDING
                                AscAckInterrupt(iop_base);
 #endif
index b00a41c..b179340 100644 (file)
@@ -642,26+642,6 @@ int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
     scsi_result[1] |= 0x80;     /* removable */
   }
 
-  if (!strncmp (scsi_result + 8, "NEC", 3)) {
-    if (!strncmp (scsi_result + 16, "CD-ROM DRIVE:84 ", 16) ||
-        !strncmp (scsi_result + 16, "CD-ROM DRIVE:25", 15))
-      SDpnt->manufacturer = SCSI_MAN_NEC_OLDCDR;
-    else
-      SDpnt->manufacturer = SCSI_MAN_NEC;
-  }
-  else if (!strncmp (scsi_result + 8, "TOSHIBA", 7))
-    SDpnt->manufacturer = SCSI_MAN_TOSHIBA;
-  else if (!strncmp (scsi_result + 8, "SONY", 4))
-    SDpnt->manufacturer = SCSI_MAN_SONY;
-  else if (!strncmp (scsi_result + 8, "PIONEER", 7))
-    SDpnt->manufacturer = SCSI_MAN_PIONEER;
-  else if (!strncmp (scsi_result + 8, "MATSHITA", 8))
-    SDpnt->manufacturer = SCSI_MAN_MATSHITA;
-  else if (!strncmp (scsi_result + 8, "HP", 2))
-    SDpnt->manufacturer = SCSI_MAN_HP;
-  else
-    SDpnt->manufacturer = SCSI_MAN_UNKNOWN;
-
   memcpy (SDpnt->vendor, scsi_result + 8, 8);
   memcpy (SDpnt->model, scsi_result + 16, 16);
   memcpy (SDpnt->rev, scsi_result + 32, 4);
index 4007254..e35bed8 100644 (file)
@@ -123,19+123,6 @@ extern const unsigned char scsi_command_size[8];
  */
 
 /*
- *      Manufacturers list
- */
-
-#define SCSI_MAN_UNKNOWN     0
-#define SCSI_MAN_NEC         1
-#define SCSI_MAN_TOSHIBA     2
-#define SCSI_MAN_NEC_OLDCDR  3
-#define SCSI_MAN_SONY        4
-#define SCSI_MAN_PIONEER     5
-#define SCSI_MAN_MATSHITA    6
-#define SCSI_MAN_HP          7
-
-/*
  *  As the scsi do command functions are intelligent, and may need to
  *  redo a command, we need to keep track of the last command
  *  executed on each one.
index 5bc6731..8e7f2ff 100644 (file)
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
+#include <asm/io.h>
 
 #define MAJOR_NR SCSI_DISK_MAJOR
 #include <linux/blk.h>
@@ -660,10+661,10 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
      * a bounce buffer if we are straddling the 16Mb line 
      */ 
     if (contiguous && SCpnt->request.bh &&
-       ((long) SCpnt->request.bh->b_data) 
+      virt_to_phys(SCpnt->request.bh->b_data) 
        + (SCpnt->request.nr_sectors << 9) - 1 > ISA_DMA_THRESHOLD 
        && SCpnt->host->unchecked_isa_dma) {
-       if(((long) SCpnt->request.bh->b_data) > ISA_DMA_THRESHOLD)
+      if(virt_to_phys(SCpnt->request.bh->b_data) > ISA_DMA_THRESHOLD)
            bounce_buffer = (char *) scsi_malloc(bounce_size);
        if(!bounce_buffer) contiguous = 0;
     }
@@ -720,7+721,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
            if(!bhp || !CONTIGUOUS_BUFFERS(bhp,bh) ||
               !CLUSTERABLE_DEVICE(SCpnt) ||
               (SCpnt->host->unchecked_isa_dma &&
-               ((unsigned long) bh->b_data-1) == ISA_DMA_THRESHOLD)) {
+               virt_to_phys(bh->b_data-1) == ISA_DMA_THRESHOLD)) {
                if (count < SCpnt->host->sg_tablesize) count++;
                else break;
            }
@@ -730,7+731,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
        }
 #if 0
        if(SCpnt->host->unchecked_isa_dma &&
-          ((unsigned int) SCpnt->request.bh->b_data-1) == ISA_DMA_THRESHOLD) count--;
+        virt_to_phys(SCpnt->request.bh->b_data-1) == ISA_DMA_THRESHOLD) count--;
 #endif
        SCpnt->use_sg = count;  /* Number of chains */
        /* scsi_malloc can only allocate in chunks of 512 bytes */
@@ -762,7+763,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
                sgpnt[count].length += bh->b_size;
                counted += bh->b_size >> 9;
                
-               if (((long) sgpnt[count].address) + sgpnt[count].length - 1 > 
+               if (virt_to_phys(sgpnt[count].address) + sgpnt[count].length - 1 >
                    ISA_DMA_THRESHOLD && (SCpnt->host->unchecked_isa_dma) &&
                    !sgpnt[count].alt_address) {
                    sgpnt[count].alt_address = sgpnt[count].address;
@@ -809,7+810,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
                   && CLUSTERABLE_DEVICE(SCpnt)) {
                    char * tmp;
                    
-                   if (((long) sgpnt[count].address) + sgpnt[count].length +
+                 if (virt_to_phys(sgpnt[count].address) + sgpnt[count].length +
                        bhp->b_size - 1 > ISA_DMA_THRESHOLD && 
                        (SCpnt->host->unchecked_isa_dma) &&
                        !sgpnt[count].alt_address) continue;
@@ -871,7+872,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
     /* Now handle the possibility of DMA to addresses > 16Mb */
     
     if(SCpnt->use_sg == 0){
-       if (((long) buff) + (this_count << 9) - 1 > ISA_DMA_THRESHOLD && 
+      if (virt_to_phys(buff) + (this_count << 9) - 1 > ISA_DMA_THRESHOLD && 
            (SCpnt->host->unchecked_isa_dma)) {
            if(bounce_buffer)
                buff = bounce_buffer;
index f20f6db..1f4d53c 100644 (file)
  *      Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to
  *      provide auto-eject.
  *
+ *          Modified by Gerd Knorr <kraxel@cs.tu-berlin.de> to support the
+ *          generic cdrom interface
+ *
  */
 
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
+#include <linux/ucdrom.h>
 #include <linux/interrupt.h>
+#include <linux/config.h>
 #include <asm/system.h>
 
 #define MAJOR_NR SCSI_CDROM_MAJOR
@@ -49,53+54,48 @@ static int sr_detect(Scsi_Device *);
 static void sr_detach(Scsi_Device *);
 
 struct Scsi_Device_Template sr_template = {NULL, "cdrom", "sr", NULL, TYPE_ROM, 
-                                              SCSI_CDROM_MAJOR, 0, 0, 0, 1,
-                                              sr_detect, sr_init,
-                                              sr_finish, sr_attach, sr_detach};
+                                           SCSI_CDROM_MAJOR, 0, 0, 0, 1,
+                                           sr_detect, sr_init,
+                                           sr_finish, sr_attach, sr_detach};
 
 Scsi_CD * scsi_CDs = NULL;
 static int * sr_sizes;
 
 static int * sr_blocksizes;
 
-static int sr_open(struct inode *, struct file *);
+static int sr_open(struct cdrom_device_info*, int);
 void get_sectorsize(int);
-void sr_photocd(struct inode *);
-
-extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 void requeue_sr_request (Scsi_Cmnd * SCpnt);
-static int check_cdrom_media_change(kdev_t);
+static int sr_media_change(struct cdrom_device_info*, int);
 
-static void sr_release(struct inode * inode, struct file * file)
+static void sr_release(struct cdrom_device_info *cdi)
 {
-       sync_dev(inode->i_rdev);
-       if(! --scsi_CDs[MINOR(inode->i_rdev)].device->access_count)
-       {
-           sr_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
-           if (scsi_CDs[MINOR(inode->i_rdev)].auto_eject)
-               sr_ioctl(inode, NULL, CDROMEJECT, 0);
-       }
-       if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)
-           (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)--;
+       sync_dev(cdi->dev);
+       scsi_CDs[MINOR(cdi->dev)].device->access_count--;
+       if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->usage_count)
+           (*scsi_CDs[MINOR(cdi->dev)].device->host->hostt->usage_count)--;
        if(sr_template.usage_count) (*sr_template.usage_count)--;
 }
 
-static struct file_operations sr_fops = 
-{
-       NULL,                   /* lseek - default */
-       block_read,             /* read - general block-dev read */
-       block_write,            /* write - general block-dev write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* select */
-       sr_ioctl,               /* ioctl */
-       NULL,                   /* mmap */
-       sr_open,        /* special open code */
-       sr_release,             /* release */
-       NULL,                   /* fsync */
-       NULL,                   /* fasync */
-       check_cdrom_media_change,  /* Disk change */
-       NULL                    /* revalidate */
+static struct cdrom_device_ops sr_dops = {
+        sr_open,                      /* open */
+        sr_release,                   /* release */
+        sr_drive_status,              /* drive status */
+        sr_disk_status,               /* disc status */
+        sr_media_change,              /* media changed */
+        sr_tray_move,                 /* tray move */
+        sr_lock_door,                 /* lock door */
+        NULL,                         /* select speed */
+        NULL,                         /* select disc */
+        sr_get_last_session,          /* get last session */
+        sr_get_mcn,                   /* get universal product code */
+        sr_reset,                     /* hard reset */
+        sr_audio_ioctl,               /* audio ioctl */
+        sr_dev_ioctl,                 /* device-specific ioctl */
+        CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK |
+        CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO,
+        0
 };
 
 /*
@@ -108,38+108,38 @@ static struct file_operations sr_fops =
  * an inode for that to work, and we do not always have one.
  */
 
-int check_cdrom_media_change(kdev_t full_dev){
-       int retval, target;
-       struct inode inode;
-       int flag = 0;
-    
-       target =  MINOR(full_dev);
-    
-       if (target >= sr_template.nr_dev) {
-               printk("CD-ROM request error: invalid device.\n");
-               return 0;
-       };
-    
-       inode.i_rdev = full_dev;  /* This is all we really need here */
-       retval = sr_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
+int sr_media_change(struct cdrom_device_info *cdi, int slot){
+       int retval;
+
+        if (CDSL_CURRENT != slot) {
+                /* no changer support */
+                return -EINVAL;
+        }
+        
+       retval = scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+                            SCSI_IOCTL_TEST_UNIT_READY, 0);
     
-       if(retval){ /* Unable to test, unit probably not ready.  This usually
+       if(retval){
+                /* Unable to test, unit probably not ready.  This usually
                 * means there is no disc in the drive.  Mark as changed,
                 * and we will figure it out later once the drive is
                 * available again.  */
        
-       scsi_CDs[target].device->changed = 1;
-       return 1; /* This will force a flush, if called from
-                  * check_disk_change */
+                scsi_CDs[MINOR(cdi->dev)].device->changed = 1;
+                return 1; /* This will force a flush, if called from
+                           * check_disk_change */
        };
     
-       retval = scsi_CDs[target].device->changed;
-       if(!flag) {
-       scsi_CDs[target].device->changed = 0;
-       /* If the disk changed, the capacity will now be different,
-        * so we force a re-read of this information */
-       if (retval) scsi_CDs[target].needs_sector_size = 1;
-       };
+       retval = scsi_CDs[MINOR(cdi->dev)].device->changed;
+        scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
+        /* If the disk changed, the capacity will now be different,
+         * so we force a re-read of this information */
+        if (retval) {
+#ifdef CONFIG_BLK_DEV_SR_VENDOR
+                sr_cd_check(cdi);
+#endif
+                scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
+        }
        return retval;
 }
 
@@ -361,317+361,26 @@ static void rw_intr (Scsi_Cmnd * SCpnt)
     }
 }
 
-/*
- * Here I tried to implement support for multisession-CD's
- * 
- * Much of this has do be done with vendor-specific SCSI-commands, because
- * multisession is newer than the SCSI-II standard.
- * So I have to complete it step by step. Useful information is welcome.
- *
- * Actually works:
- *   - NEC:     Detection and support of multisession CD's. Special handling
- *              for XA-disks is not necessary.
- *     
- *   - TOSHIBA: setting density is done here now, mounting PhotoCD's should
- *              work now without running the program "set_density"
- *              Multisession CD's are supported too.
- *
- *   Gerd Knorr <kraxel@cs.tu-berlin.de> 
- */
-/*
- * 19950704 operator@melchior.cuivre.fdn.fr (Thomas Quinot)
- *
- *   - SONY:   Same as Nec.
- *
- *   - PIONEER: works with SONY code (may be others too ?)
- *
- * 19961011
- *
- *   - HP:      reportedly working.
- */
-
-void sr_photocd(struct inode *inode)
-{
-    unsigned long   sector,min,sec,frame;
-    unsigned char   buf[40];    /* the buffer for the ioctl */
-    Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
-#define CLEAR_CMD_BUFFER memset (buf, 0, sizeof buf);
-    unsigned char   *cmd;       /* the scsi-command */
-    unsigned char   *send;      /* the data we send to the drive ... */
-    unsigned char   *rec;       /* ... and get back */
-    int             rc,is_xa,no_multi;
-    
-    if (scsi_CDs[MINOR(inode->i_rdev)].xa_flags & 0x02) {
-#ifdef DEBUG
-       printk(KERN_DEBUG "sr_photocd: CDROM and/or driver do not support multisession CD's");
-#endif
-       return;
-    }
-    
-    if (!suser()) {
-       /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed
-         * for me. That's why mpcd_sector will be initialized with zero,
-         * because I'm not able to get the right value. Necessary only if
-         * access_count is 1, else no disk change happened since the last
-         * call of this function and we can keep the old value.
-        */
-       if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count) {
-           scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = 0;
-           scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01;
-       }
-       return;
-    }
-    
-    sector   = 0;
-    is_xa    = 0;
-    no_multi = 0;
-    cmd = rec = sic->data;
-    
-    switch(scsi_CDs[MINOR(inode->i_rdev)].device->manufacturer) {
-       
-    case SCSI_MAN_NEC:
-#ifdef DEBUG
-       printk(KERN_DEBUG "sr_photocd: use NEC code\n");
-#endif
-       CLEAR_CMD_BUFFER;
-       sic->inlen  = 0x0;   /* we send nothing...     */
-       sic->outlen = 0x16;  /* and receive 0x16 bytes */
-       cmd[0] = 0xde;
-       cmd[1] = 0x03;
-       cmd[2] = 0xb0;
-       rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                          SCSI_IOCTL_SEND_COMMAND, sic);
-       if (rc != 0) {
-            if (rc != 0x28000002) /* drop "not ready" */
-                printk(KERN_WARNING"sr_photocd: ioctl error (NEC): 0x%x\n",rc);
-           break;
-       }
-       if (rec[14] != 0 && rec[14] != 0xb0) {
-           printk(KERN_INFO"sr_photocd: (NEC) Hmm, seems the CDROM doesn't support multisession CD's\n");
-           no_multi = 1;
-           break;
-       }
-       min   = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16;
-       sec   = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16;
-       frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16;
-       sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
-       is_xa  = (rec[14] == 0xb0);
-       break;
-       
-    case SCSI_MAN_TOSHIBA:
-#ifdef DEBUG
-       printk(KERN_DEBUG "sr_photocd: use TOSHIBA code\n");
-#endif
-       
-       /* we request some disc information (is it a XA-CD ?,
-        * where starts the last session ?) */
-       CLEAR_CMD_BUFFER;
-       sic->inlen  = 0; /* we send nothing...  */
-       sic->outlen = 4; /* and receive 4 bytes */
-       cmd[0]                  = (unsigned char) 0x00c7;
-       cmd[1]                  = (unsigned char) 3;
-       rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                              SCSI_IOCTL_SEND_COMMAND, sic);
-       if (rc != 0) {
-           if (rc == 0x28000002) {
-               /* Got a "not ready" - error. No chance to find out if this is
-                * because there is no CD in the drive or because the drive
-                * don't knows multisession CD's. So I need to do an extra
-                 * check... */
-               if (!kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                                      SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
-                   printk(KERN_INFO "sr_photocd: (TOSHIBA) Hmm, seems the CDROM doesn't support multisession CD's\n");
-                   no_multi = 1;
-               }
-           } else
-               printk(KERN_WARNING"sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
-           break; /* if the first ioctl fails, we don't call the second one */
-       }
-       is_xa  = (rec[0] == 0x20);
-       min    = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16;
-       sec    = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
-       frame  = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
-       sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
-       if (sector)
-           sector -= CD_BLOCK_OFFSET;
-       
-       /* now we do a get_density... */
-       CLEAR_CMD_BUFFER;
-       sic->inlen  = 0;  /* we send nothing...  */
-       sic->outlen = 12; /* and receive 12 bytes */
-       cmd[0]                  = (unsigned char) MODE_SENSE;
-       cmd[2]                  = (unsigned char) 1;
-       cmd[4]                  = (unsigned char) 12;
-       rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                              SCSI_IOCTL_SEND_COMMAND, sic);
-       if (rc != 0) {
-           printk(KERN_WARNING "sr_photocd: ioctl error (TOSHIBA #2): 0x%x\n",rc);
-           break;
-       }
-#ifdef DEBUG
-       printk(KERN_DEBUG "sr_photocd: get_density: 0x%x\n",rec[4]);
-#endif
-       
-       /* ...and only if necessary a set_density */
-       if ((rec[4] != 0x81 && is_xa) || (rec[4] != 0 && !is_xa)) {
-#ifdef DEBUG
-           printk(KERN_DEBUG "sr_photocd: doing set_density\n");
-#endif
-           CLEAR_CMD_BUFFER;
-           sic->inlen  = 12; /* we send 12 bytes... */
-           sic->outlen = 0;  /* and receive nothing */
-           cmd[0]                  = (unsigned char) MODE_SELECT;
-           cmd[1]                  = (unsigned char) (1 << 4);
-           cmd[4]                  = (unsigned char) 12;
-            send = &cmd[6];            /* this is a 6-Byte command    */
-            send[ 3]                = (unsigned char) 0x08; /* data for cmd */
-            /* density 0x81 for XA, 0 else */
-            send[ 4]                = (is_xa) ? 
-                                    (unsigned char) 0x81 : (unsigned char) 0;  
-            send[10]                = (unsigned char) 0x08;
-           rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                                  SCSI_IOCTL_SEND_COMMAND, sic);
-           if (rc != 0) {
-               printk(KERN_WARNING "sr_photocd: ioctl error (TOSHIBA #3): 0x%x\n",rc);
-           }
-           /* The set_density command may have changed the
-             * sector size or capacity. */
-           scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size = 1;
-       }
-       break;
-
-    case SCSI_MAN_SONY: /* Thomas QUINOT <thomas@melchior.cuivre.fdn.fr> */
-    case SCSI_MAN_PIONEER:
-    case SCSI_MAN_MATSHITA:
-#ifdef DEBUG
-       printk(KERN_DEBUG "sr_photocd: use SONY/PIONEER/MATSHITA code\n");
-#endif
-       get_sectorsize(MINOR(inode->i_rdev));   /* spinup (avoid timeout) */
-       CLEAR_CMD_BUFFER;
-       sic->inlen  = 0x0;  /* we send nothing...     */
-       sic->outlen = 0x0c; /* and receive 0x0c bytes */
-        
-       cmd[0] = READ_TOC;
-       cmd[8] = 0x0c;
-       cmd[9] = 0x40;
-       rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                              SCSI_IOCTL_SEND_COMMAND, sic);
-       
-       if (rc != 0) {
-            if (rc != 0x28000002) /* drop "not ready" */
-                printk(KERN_WARNING "sr_photocd: ioctl error (SONY/PIONEER/MATSHITA): 0x%x\n",rc);
-           break;
-       }
-       if ((rec[0] << 8) + rec[1] != 0x0a) {
-           printk(KERN_INFO "sr_photocd: (SONY/PIONEER/MATSHITA) Hmm, seems the CDROM doesn't support multisession CD's\n");
-           no_multi = 1;
-           break;
-       }
-       sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
-       is_xa = !!sector;
-       break;
-    case SCSI_MAN_HP:
-#define DEBUG
-#ifdef DEBUG
-        printk(KERN_DEBUG "sr_photocd: use HP code\n");
-#endif
-        CLEAR_CMD_BUFFER;
-       sic->inlen  = 0x0; /* we send nothing...  */
-       sic->outlen = 0x4; /* and receive 4 bytes */
-        cmd[0] = 0x43; /* Read TOC */
-        cmd[8] = 0x04;
-        cmd[9] = 0x40;
-        rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                               SCSI_IOCTL_SEND_COMMAND, sic);
-        if (rc != 0) {
-            if (rc != 0x28000002) /* drop "not ready" */
-                printk(KERN_WARNING "sr_photocd: ioctl error (HP-1): 0x%x\n",rc);
-       break;
-        }
-               
-        if ((rc = rec[2]) == 0) {
-          printk (KERN_WARNING "sr_photocd: (HP) No finished session");
-          break;
-        }
-        CLEAR_CMD_BUFFER;
-       sic->inlen  = 0x0;  /* we send nothing...     */
-       sic->outlen = 0x0c; /* and receive 0x0c bytes */
-        cmd[0] = 0x43; /* Read TOC */
-        cmd[6] = rc & 0x7f;  /* number of last session */
-        cmd[8] = 0x0c;
-        cmd[9] = 0x40;
-        rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-                               SCSI_IOCTL_SEND_COMMAND, sic);
-        if (rc != 0) {
-            if (rc != 0x28000002) /* drop "not ready" */
-                printk(KERN_WARNING "sr_photocd: ioctl error (HP-2): 0x%x\n",rc);
-            break;
-        }
-#undef STRICT_HP
-#ifdef STRICT_HP
-        sector = rec[11] + (rec[10] << 8) + (rec[9] << 16);
-        /* HP documentation states that Logical Start Address is
-           returned as three (!) bytes, and that rec[8] is
-           reserved. This is strange, because a LBA usually is
-           4 bytes long. */
-#else
-       sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
-#endif
-        is_xa = !!sector;
-        break;
-    case SCSI_MAN_NEC_OLDCDR:
-    case SCSI_MAN_UNKNOWN:
-    default:
-       sector = 0;
-       no_multi = 1;
-       break; }
-    
-#ifdef DEBUG
-    if (sector)
-        printk (KERN_DEBUG "sr_photocd: multisession CD detected. start: %lu\n",sector);
-#endif
-#undef DEBUG
-
-    scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = sector;
-    if (is_xa)
-       scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x01;
-    else
-       scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01;
-    if (no_multi)
-       scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x02;
-    return;
-}
-
-static int sr_open(struct inode * inode, struct file * filp)
+static int sr_open(struct cdrom_device_info *cdi, int purpose)
 {
-    if(MINOR(inode->i_rdev) >= sr_template.nr_dev || 
-       !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENXIO;   /* No such device */
-
-    if (filp->f_mode & 2)  
-       return -EROFS;
+    check_disk_change(cdi->dev);
 
-    check_disk_change(inode->i_rdev);
-    
-    if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++)
-       sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
-    if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)
-       (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)++;
+    scsi_CDs[MINOR(cdi->dev)].device->access_count++;
+    if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->usage_count)
+       (*scsi_CDs[MINOR(cdi->dev)].device->host->hostt->usage_count)++;
     if(sr_template.usage_count) (*sr_template.usage_count)++;
-    
-    sr_photocd(inode);
-    
+
     /* If this device did not have media in the drive at boot time, then
      * we would have been unable to get the sector size.  Check to see if
      * this is the case, and try again.
      */
 
-    if(scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size)
-       get_sectorsize(MINOR(inode->i_rdev));
+    if(scsi_CDs[MINOR(cdi->dev)].needs_sector_size)
+       get_sectorsize(MINOR(cdi->dev));
 
     return 0;
 }
 
-
 /*
  * do_sr_request() is the request handler function for the sr driver.
  * Its function in life is to take block device requests, and
@@ -1079,6+788,19 @@ static int sr_attach(Scsi_Device * SDp){
     
     SDp->scsi_request_fn = do_sr_request;
     scsi_CDs[i].device = SDp;
+    
+    scsi_CDs[i].cdi.ops        = &sr_dops;
+    scsi_CDs[i].cdi.handle     = &scsi_CDs[i];
+    scsi_CDs[i].cdi.dev        = MKDEV(MAJOR_NR,i);
+    scsi_CDs[i].cdi.mask       = 0;
+    scsi_CDs[i].cdi.speed      = 1;
+    scsi_CDs[i].cdi.capacity   = 1;
+    register_cdrom(&scsi_CDs[i].cdi, "sr");
+            
+#ifdef CONFIG_BLK_DEV_SR_VENDOR
+    sr_vendor_init(i);
+#endif
+
     sr_template.nr_dev++;
     if(sr_template.nr_dev > sr_template.dev_max)
        panic ("scsi_devices corrupt (sr)");
@@ -1184,7+906,7 @@ static int sr_init()
     if(sr_template.dev_noticed == 0) return 0;
 
     if(!sr_registered) {
-       if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) {
+       if (register_blkdev(MAJOR_NR,"sr",&cdrom_fops)) {
            printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR);
            return 1;
        }
@@ -1193,7+915,8 @@ static int sr_init()
 
     
     if (scsi_CDs) return 0;
-    sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS;
+    sr_template.dev_max =
+            sr_template.dev_noticed + SR_EXTRA_DEVS;
     scsi_CDs = (Scsi_CD *) scsi_init_malloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);
     memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD));
 
@@ -1222,6+945,7 @@ void sr_finish()
        scsi_CDs[i].capacity = 0x1fffff;
        scsi_CDs[i].sector_size = 2048;  /* A guess, just in case */
        scsi_CDs[i].needs_sector_size = 1;
+       scsi_CDs[i].device->changed = 1; /* force recheck CD type */
 #if 0
        /* seems better to leave this for later */
        get_sectorsize(i);
@@ -1230,7+954,6 @@ void sr_finish()
        scsi_CDs[i].use = 1;
        scsi_CDs[i].ten = 1;
        scsi_CDs[i].remap = 1;
-       scsi_CDs[i].auto_eject = 0; /* Default is not to eject upon unmount. */
        sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
     }
     
@@ -1266,6+989,7 @@ static void sr_detach(Scsi_Device * SDp)
             * Reset things back to a sane state so that one can re-load a new
             * driver (perhaps the same one).
             */
+            unregister_cdrom(&(cpnt->cdi));
            cpnt->device = NULL;
            cpnt->capacity = 0;
            SDp->attached--;
@@ -1281,14+1005,14 @@ static void sr_detach(Scsi_Device * SDp)
 #ifdef MODULE
 
 int init_module(void) {
-    sr_template.usage_count = &mod_use_count_;
-    return scsi_register_module(MODULE_SCSI_DEV, &sr_template);
+        sr_template.usage_count = &mod_use_count_;
+        return scsi_register_module(MODULE_SCSI_DEV, &sr_template);
 }
 
 void cleanup_module( void) 
 {
     scsi_unregister_module(MODULE_SCSI_DEV, &sr_template);
-    unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
+    unregister_blkdev(MAJOR_NR, "sr");
     sr_registered--;
     if(scsi_CDs != NULL) {
        scsi_init_free((char *) scsi_CDs,
index 381678a..5b2a087 100644 (file)
 #ifndef _SR_H
 #define _SR_H
 
+#include <linux/config.h>
+
 #include "scsi.h"
 
 typedef struct
        {
        unsigned        capacity;               /* size in blocks                       */
        unsigned        sector_size;            /* size in bytes                        */
-       Scsi_Device     *device;                
-       unsigned long   mpcd_sector;            /* for reading multisession-CD's        */
-       char            xa_flags;               /* some flags for handling XA-CD's      */
+       Scsi_Device     *device;
+        unsigned int    vendor;                 /* vendor code, see sr_vendor.c         */
+       unsigned long   ms_offset;              /* for reading multisession-CD's        */
        unsigned char   sector_bit_size;        /* sector size = 2^sector_bit_size      */
        unsigned char   sector_bit_shift;       /* sectors/FS block = 2^sector_bit_shift*/
        unsigned        needs_sector_size:1;    /* needs to get sector size */
        unsigned        ten:1;                  /* support ten byte commands            */
        unsigned        remap:1;                /* support remapping                    */
        unsigned        use:1;                  /* is this device still supportable     */
-       unsigned        auto_eject:1;           /* auto-eject medium on last release.   */
+       unsigned        xa_flag:1;              /* CD has XA sectors */
+       struct cdrom_device_info cdi;
        } Scsi_CD;
        
 extern Scsi_CD * scsi_CDs;
 
+int sr_do_ioctl(int, unsigned char*, void*, unsigned);
+
+int sr_lock_door(struct cdrom_device_info*, int);
+int sr_tray_move(struct cdrom_device_info*, int);
+int sr_drive_status(struct cdrom_device_info*, int);
+int sr_disk_status(struct cdrom_device_info*);
+int sr_get_last_session(struct cdrom_device_info*, struct cdrom_multisession*);
+int sr_get_mcn(struct cdrom_device_info*, struct cdrom_mcn*);
+int sr_reset(struct cdrom_device_info*);
+int sr_audio_ioctl(struct cdrom_device_info*, unsigned int, void*);
+int sr_dev_ioctl(struct cdrom_device_info*, unsigned int, unsigned long);
+
+/* vendor-specific */
+#ifdef CONFIG_BLK_DEV_SR_VENDOR
+void sr_vendor_init(int minor);
+int sr_cd_check(struct cdrom_device_info*);
+#endif
+
 #endif
index 82884f4..73c54d4 100644 (file)
 #include <linux/blk.h>
 #include "scsi.h"
 #include "hosts.h"
-#include "sr.h"
 #include <scsi/scsi_ioctl.h>
 
 #include <linux/cdrom.h>
+#include <linux/ucdrom.h>
+#include "sr.h"
 
 extern void get_sectorsize(int);
-extern void sr_photocd(struct inode *);
 
 #define IOCTL_RETRIES 3
 /* The CDROM is fairly slow, so we need a little extra time */
@@ -38,7+38,7 @@ static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
    error code is.  Normally the UNIT_ATTENTION code will automatically
    clear after one error */
 
-static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength)
+int sr_do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength)
 {
     Scsi_Cmnd * SCpnt;
     int result;
@@ -88,17+88,134 @@ static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned
     return result;
 }
 
-int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
+/* ---------------------------------------------------------------------- */
+/* interface to cdrom.c                                                   */
+
+int sr_tray_move(struct cdrom_device_info *cdi, int pos)
 {
-    u_char  sr_cmd[10];
-    
-    kdev_t dev = inode->i_rdev;
-    int result, target, err;
-    
-    target = MINOR(dev);
+        u_char  sr_cmd[10];
+        
+        sr_cmd[0] = START_STOP;
+        sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device -> lun) << 5);
+        sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
+        sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */;
+       
+        return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 255);
+}
+
+int sr_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+        return scsi_ioctl (scsi_CDs[MINOR(cdi->dev)].device,
+                           lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
+                           0);
+}
+
+int sr_drive_status(struct cdrom_device_info *cdi, int slot)
+{
+        if (CDSL_CURRENT != slot) {
+                /* we have no changer support */
+                return -EINVAL;
+        }
+
+        if (!scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+                        SCSI_IOCTL_TEST_UNIT_READY,0))
+                return CDS_DISC_OK;
+
+#if 0
+        /* Enable this if you want to try auto-close. Is'nt enabled by
+         * default because it does'nt work perfectly (no way to
+         * difference between "tray open" and "tray closed, no disk"),
+         * and for caddy drives this is useless anyway. */
+        return CDS_TRAY_OPEN;
+#else
+        return CDS_NO_DISC;
+#endif
+}
+
+int sr_disk_status(struct cdrom_device_info *cdi)
+{
+       struct cdrom_tochdr    toc_h;
+       struct cdrom_tocentry  toc_e;
+        int                    i;
+
+        if (scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,SCSI_IOCTL_TEST_UNIT_READY,0))
+                return CDS_NO_DISC;
+
+        /* if the xa-bit is on, we tell it is XA... */
+        if (scsi_CDs[MINOR(cdi->dev)].xa_flag)
+                return CDS_XA_2_1;
+        
+        /* ...else we look for data tracks */
+        if (sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))
+                return CDS_NO_INFO;
+        for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
+                toc_e.cdte_track  = i;
+                toc_e.cdte_format = CDROM_LBA;
+                if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e))
+                        return CDS_NO_INFO;
+                if (toc_e.cdte_ctrl & CDROM_DATA_TRACK)
+                        return CDS_DATA_1;
+#if 0
+                if (i == toc_h.cdth_trk0 && toc_e.cdte_addr.lba > 100)
+                        /* guess: looks like a "hidden track" CD */
+                        return CDS_DATA_1;
+#endif
+        }
+        return CDS_AUDIO;
+}
+
+int sr_get_last_session(struct cdrom_device_info *cdi,
+                        struct cdrom_multisession* ms_info)
+{
+        ms_info->addr.lba=scsi_CDs[MINOR(cdi->dev)].ms_offset;
+        ms_info->xa_flag=scsi_CDs[MINOR(cdi->dev)].xa_flag;
+
+       return 0;
+}
+
+int sr_get_mcn(struct cdrom_device_info *cdi,struct cdrom_mcn *mcn)
+{
+        u_char  sr_cmd[10];
+       char * buffer;
+        int result;
+               
+       sr_cmd[0] = SCMD_READ_SUBCHANNEL;
+       sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5);
+       sr_cmd[2] = 0x40;    /* I do want the subchannel info */
+       sr_cmd[3] = 0x02;    /* Give me medium catalog number info */
+       sr_cmd[4] = sr_cmd[5] = 0;
+       sr_cmd[6] = 0;
+       sr_cmd[7] = 0;
+       sr_cmd[8] = 24;
+       sr_cmd[9] = 0;
+       
+       buffer = (unsigned char*) scsi_malloc(512);
+       if(!buffer) return -ENOMEM;
+       
+       result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24);
+       
+       memcpy (mcn->medium_catalog_number, buffer + 9, 13);
+        mcn->medium_catalog_number[13] = 0;
+
+       scsi_free(buffer, 512);
+       
+       return result;
+}
+
+int sr_reset(struct cdrom_device_info *cdi)
+{
+       invalidate_buffers(cdi->dev);
+       return 0;        
+}
+
+/* ----------------------------------------------------------------------- */
+
+int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void* arg)
+{
+    u_char  sr_cmd[10];    
+    int result, target;
     
-    if (target >= sr_template.nr_dev ||
-       !scsi_CDs[target].device) return -ENXIO;
+    target = MINOR(cdi->dev);
     
     switch (cmd) 
     {
@@ -112,8+229,8 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        sr_cmd[8] = 0;
        sr_cmd[9] = 0;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       return result;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);
+        break;
        
     case CDROMRESUME:
        
@@ -124,86+241,69 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        sr_cmd[8] = 1;
        sr_cmd[9] = 0;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       
-       return result;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);        
+        break;
        
     case CDROMPLAYMSF:
     {
-       struct cdrom_msf msf;
+       struct cdrom_msf* msf = (struct cdrom_msf*)arg;
 
-        err = verify_area (VERIFY_READ, (void *) arg, sizeof (msf));
-        if (err) return err;
-
-       copy_from_user(&msf, (void *) arg, sizeof(msf));
-       
        sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
        sr_cmd[1] = scsi_CDs[target].device->lun << 5;
        sr_cmd[2] = 0;
-       sr_cmd[3] = msf.cdmsf_min0;
-       sr_cmd[4] = msf.cdmsf_sec0;
-       sr_cmd[5] = msf.cdmsf_frame0;
-       sr_cmd[6] = msf.cdmsf_min1;
-       sr_cmd[7] = msf.cdmsf_sec1;
-       sr_cmd[8] = msf.cdmsf_frame1;
+       sr_cmd[3] = msf->cdmsf_min0;
+       sr_cmd[4] = msf->cdmsf_sec0;
+       sr_cmd[5] = msf->cdmsf_frame0;
+       sr_cmd[6] = msf->cdmsf_min1;
+       sr_cmd[7] = msf->cdmsf_sec1;
+       sr_cmd[8] = msf->cdmsf_frame1;
        sr_cmd[9] = 0;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       return result;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);
+        break;
     }
 
     case CDROMPLAYBLK:
     {
-       struct cdrom_blk blk;
-
-        err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk));
-        if (err) return err;
+       struct cdrom_blk* blk = (struct cdrom_blk*)arg;
 
-       copy_from_user(&blk, (void *) arg, sizeof(blk));
-       
        sr_cmd[0] = SCMD_PLAYAUDIO10;
        sr_cmd[1] = scsi_CDs[target].device->lun << 5;
-       sr_cmd[2] = blk.from >> 24;
-       sr_cmd[3] = blk.from >> 16;
-       sr_cmd[4] = blk.from >> 8;
-       sr_cmd[5] = blk.from;
+       sr_cmd[2] = blk->from >> 24;
+       sr_cmd[3] = blk->from >> 16;
+       sr_cmd[4] = blk->from >> 8;
+       sr_cmd[5] = blk->from;
        sr_cmd[6] = 0;
-       sr_cmd[7] = blk.len >> 8;
-       sr_cmd[8] = blk.len;
+       sr_cmd[7] = blk->len >> 8;
+       sr_cmd[8] = blk->len;
        sr_cmd[9] = 0;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       return result;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);
+        break;
     }
                
     case CDROMPLAYTRKIND:
     {
-       struct cdrom_ti ti;
-
-        err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti));
-        if (err) return err;
+       struct cdrom_ti* ti = (struct cdrom_ti*)arg;
 
-       copy_from_user(&ti, (void *) arg, sizeof(ti));
-       
        sr_cmd[0] = SCMD_PLAYAUDIO_TI;
        sr_cmd[1] = scsi_CDs[target].device->lun << 5;
        sr_cmd[2] = 0;
        sr_cmd[3] = 0;
-       sr_cmd[4] = ti.cdti_trk0;
-       sr_cmd[5] = ti.cdti_ind0;
+       sr_cmd[4] = ti->cdti_trk0;
+       sr_cmd[5] = ti->cdti_ind0;
        sr_cmd[6] = 0;
-       sr_cmd[7] = ti.cdti_trk1;
-       sr_cmd[8] = ti.cdti_ind1;
+       sr_cmd[7] = ti->cdti_trk1;
+       sr_cmd[8] = ti->cdti_ind1;
        sr_cmd[9] = 0;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       
-       return result;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);
+        break;
     }
        
     case CDROMREADTOCHDR:
     {
-       struct cdrom_tochdr tochdr;
+       struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
        char * buffer;
        
        sr_cmd[0] = SCMD_READ_TOC;
@@ -217,36+317,25 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        buffer = (unsigned char *) scsi_malloc(512);
        if(!buffer) return -ENOMEM;
        
-       result = do_ioctl(target, sr_cmd, buffer, 12);
+       result = sr_do_ioctl(target, sr_cmd, buffer, 12);
        
-       tochdr.cdth_trk0 = buffer[2];
-       tochdr.cdth_trk1 = buffer[3];
+       tochdr->cdth_trk0 = buffer[2];
+       tochdr->cdth_trk1 = buffer[3];
        
        scsi_free(buffer, 512);
-       
-       err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
-       if (err)
-           return err;
-       copy_to_user ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
-       
-       return result;
+        break;
     }
        
     case CDROMREADTOCENTRY:
     {
-       struct cdrom_tocentry tocentry;
+       struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
        unsigned char * buffer;
        
-        err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));
-        if (err) return err;
-
-       copy_from_user (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
-       
        sr_cmd[0] = SCMD_READ_TOC;
        sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) |
-          (tocentry.cdte_format == CDROM_MSF ? 0x02 : 0);
+          (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
        sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
-       sr_cmd[6] = tocentry.cdte_track;
+       sr_cmd[6] = tocentry->cdte_track;
        sr_cmd[7] = 0;             /* MSB of length (12)  */
        sr_cmd[8] = 12;            /* LSB of length */
        sr_cmd[9] = 0;
@@ -254,28+343,21 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        buffer = (unsigned char *) scsi_malloc(512);
        if(!buffer) return -ENOMEM;
        
-       result = do_ioctl (target, sr_cmd, buffer, 12);
-       
-        tocentry.cdte_ctrl = buffer[5] & 0xf;  
-        tocentry.cdte_adr = buffer[5] >> 4;
-        tocentry.cdte_datamode = (tocentry.cdte_ctrl & 0x04) ? 1 : 0;
-       if (tocentry.cdte_format == CDROM_MSF) {
-           tocentry.cdte_addr.msf.minute = buffer[9];
-           tocentry.cdte_addr.msf.second = buffer[10];
-           tocentry.cdte_addr.msf.frame = buffer[11];
-       }
-       else
-           tocentry.cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
+       result = sr_do_ioctl (target, sr_cmd, buffer, 12);
+       
+        tocentry->cdte_ctrl = buffer[5] & 0xf; 
+        tocentry->cdte_adr = buffer[5] >> 4;
+        tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
+       if (tocentry->cdte_format == CDROM_MSF) {
+           tocentry->cdte_addr.msf.minute = buffer[9];
+           tocentry->cdte_addr.msf.second = buffer[10];
+           tocentry->cdte_addr.msf.frame = buffer[11];
+       } else
+           tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
                                        + buffer[10]) << 8) + buffer[11];
        
        scsi_free(buffer, 512);
-       
-       err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));
-       if (err)
-           return err;
-       copy_to_user ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
-       
-       return result;
+        break;
     }
        
     case CDROMSTOP:
@@ -284,8+366,8 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
        sr_cmd[4] = 0;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       return result;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);
+        break;
        
     case CDROMSTART:
        sr_cmd[0] = START_STOP;
@@ -293,59+375,13 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
        sr_cmd[4] = 1;
        
-       result = do_ioctl(target, sr_cmd, NULL, 255);
-       return result;
-       
-    case CDROMCLOSETRAY:
-       sr_cmd[0] = START_STOP;
-       sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5);
-       sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
-       sr_cmd[4] = 0x03;
-       
-        if ((result = do_ioctl(target, sr_cmd, NULL, 255)))
-          return result;
-
-        /* Gather information about newly inserted disc */
-        check_disk_change (inode->i_rdev);
-        sr_ioctl (inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
-        sr_photocd (inode);
-
-        if (scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size)
-          get_sectorsize (MINOR(inode->i_rdev));
-
-        return 0;
-
-    case CDROMEJECT:
-        /*
-         * Allow 0 for access count for auto-eject feature.
-         */
-       if (scsi_CDs[target].device -> access_count > 1)
-           return -EBUSY;
-       
-       sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
-       sr_cmd[0] = START_STOP;
-       sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1;
-       sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
-       sr_cmd[4] = 0x02;
-       
-       if (!(result = do_ioctl(target, sr_cmd, NULL, 255)))
-           scsi_CDs[target].device -> changed = 1;
+       result = sr_do_ioctl(target, sr_cmd, NULL, 255);
+        break;
        
-       return result;
-       
-    case CDROMEJECT_SW:
-        scsi_CDs[target].auto_eject = !!arg;
-        return 0;
-
     case CDROMVOLCTRL:
     {
        char * buffer, * mask;
-       struct cdrom_volctrl volctrl;
-       
-        err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));
-        if (err) return err;
-
-       copy_from_user (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
+       struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
        
        /* First we get the current params so we can just twiddle the volume */
        
@@ -359,10+395,10 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        buffer = (unsigned char *) scsi_malloc(512);
        if(!buffer) return -ENOMEM;
        
-       if ((result = do_ioctl (target, sr_cmd, buffer, 28))) {
+       if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28))) {
            printk ("Hosed while obtaining audio mode page\n");
            scsi_free(buffer, 512);
-           return result;
+            break;
        }
        
        sr_cmd[0] = MODE_SENSE;
@@ -375,23+411,24 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        mask = (unsigned char *) scsi_malloc(512);
        if(!mask) {
            scsi_free(buffer, 512);
-           return -ENOMEM;
+           result = -ENOMEM;
+            break;
        };
 
-       if ((result = do_ioctl (target, sr_cmd, mask, 28))) {
+       if ((result = sr_do_ioctl (target, sr_cmd, mask, 28))) {
            printk ("Hosed while obtaining mask for audio mode page\n");
            scsi_free(buffer, 512);
            scsi_free(mask, 512);
-           return result;
+           break;
        }
        
        /* Now mask and substitute our own volume and reuse the rest */
        buffer[0] = 0;  /* Clear reserved field */
        
-       buffer[21] = volctrl.channel0 & mask[21];
-       buffer[23] = volctrl.channel1 & mask[23];
-       buffer[25] = volctrl.channel2 & mask[25];
-       buffer[27] = volctrl.channel3 & mask[27];
+       buffer[21] = volctrl->channel0 & mask[21];
+       buffer[23] = volctrl->channel1 & mask[23];
+       buffer[25] = volctrl->channel2 & mask[25];
+       buffer[27] = volctrl->channel3 & mask[27];
        
        sr_cmd[0] = MODE_SELECT;
        sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10;    /* Params are SCSI-2 */
@@ -399,19+436,16 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        sr_cmd[4] = 28;
        sr_cmd[5] = 0;
        
-       result = do_ioctl (target, sr_cmd, buffer, 28);
+       result = sr_do_ioctl (target, sr_cmd, buffer, 28);
        scsi_free(buffer, 512);
        scsi_free(mask, 512);
-       return result;
+        break;
     }
        
     case CDROMVOLREAD:
     {
        char * buffer;
-       struct cdrom_volctrl volctrl;
-       
-        err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_volctrl));
-        if (err) return err;
+       struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
        
        /* Get the current params */
        
@@ -425,27+459,24 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        buffer = (unsigned char *) scsi_malloc(512);
        if(!buffer) return -ENOMEM;
        
-       if ((result = do_ioctl (target, sr_cmd, buffer, 28))) {
+       if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28))) {
            printk ("(CDROMVOLREAD) Hosed while obtaining audio mode page\n");
            scsi_free(buffer, 512);
-           return result;
+            break;
        }
 
-       volctrl.channel0 = buffer[21];
-       volctrl.channel1 = buffer[23];
-       volctrl.channel2 = buffer[25];
-       volctrl.channel3 = buffer[27];
-
-       copy_to_user ((void *) arg, &volctrl, sizeof (struct cdrom_volctrl));
+       volctrl->channel0 = buffer[21];
+       volctrl->channel1 = buffer[23];
+       volctrl->channel2 = buffer[25];
+       volctrl->channel3 = buffer[27];
 
        scsi_free(buffer, 512);
-
-       return 0;
+        break;
     }
        
     case CDROMSUBCHNL:
     {
-       struct cdrom_subchnl subchnl;
+       struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
        char * buffer;
        
        sr_cmd[0] = SCMD_READ_SUBCHANNEL;
@@ -461,98+492,46 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        buffer = (unsigned char*) scsi_malloc(512);
        if(!buffer) return -ENOMEM;
        
-       result = do_ioctl(target, sr_cmd, buffer, 16);
+       result = sr_do_ioctl(target, sr_cmd, buffer, 16);
        
-       subchnl.cdsc_audiostatus = buffer[1];
-       subchnl.cdsc_format = CDROM_MSF;
-       subchnl.cdsc_ctrl = buffer[5] & 0xf;
-       subchnl.cdsc_trk = buffer[6];
-       subchnl.cdsc_ind = buffer[7];
+       subchnl->cdsc_audiostatus = buffer[1];
+       subchnl->cdsc_format = CDROM_MSF;
+       subchnl->cdsc_ctrl = buffer[5] & 0xf;
+       subchnl->cdsc_trk = buffer[6];
+       subchnl->cdsc_ind = buffer[7];
        
-       subchnl.cdsc_reladdr.msf.minute = buffer[13];
-       subchnl.cdsc_reladdr.msf.second = buffer[14];
-       subchnl.cdsc_reladdr.msf.frame = buffer[15];
-       subchnl.cdsc_absaddr.msf.minute = buffer[9];
-       subchnl.cdsc_absaddr.msf.second = buffer[10];
-       subchnl.cdsc_absaddr.msf.frame = buffer[11];
+       subchnl->cdsc_reladdr.msf.minute = buffer[13];
+       subchnl->cdsc_reladdr.msf.second = buffer[14];
+       subchnl->cdsc_reladdr.msf.frame = buffer[15];
+       subchnl->cdsc_absaddr.msf.minute = buffer[9];
+       subchnl->cdsc_absaddr.msf.second = buffer[10];
+       subchnl->cdsc_absaddr.msf.frame = buffer[11];
        
        scsi_free(buffer, 512);
-       
-       err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
-       if (err)
-           return err;
-       copy_to_user ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
-       return result;
+        break;
     }
-       
-    case CDROM_GET_UPC:
-    {
-       struct cdrom_mcn mcn;
-       char * buffer;
-       
-       sr_cmd[0] = SCMD_READ_SUBCHANNEL;
-       sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5);
-       sr_cmd[2] = 0x40;    /* I do want the subchannel info */
-       sr_cmd[3] = 0x02;    /* Give me medium catalog number info */
-       sr_cmd[4] = sr_cmd[5] = 0;
-       sr_cmd[6] = 0;
-       sr_cmd[7] = 0;
-       sr_cmd[8] = 24;
-       sr_cmd[9] = 0;
-       
-       buffer = (unsigned char*) scsi_malloc(512);
-       if(!buffer) return -ENOMEM;
-       
-       result = do_ioctl(target, sr_cmd, buffer, 24);
-       
-       memcpy (mcn.medium_catalog_number, buffer + 9, 13);
-        mcn.medium_catalog_number[13] = 0;
-
-       scsi_free(buffer, 512);
-       
-       err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_mcn));
-       if (err)
-           return err;
-       copy_to_user ((void *) arg, &mcn, sizeof (struct cdrom_mcn));
-       return result;
+    default:
+        return -EINVAL;
     }
+
+    if (result)
+        printk("DEBUG: sr_audio: result for ioctl %x: %x\n",cmd,result);
+    
+    return result;
+}
        
+int sr_dev_ioctl(struct cdrom_device_info *cdi,
+                 unsigned int cmd, unsigned long arg)
+{
+    int target, err;
+    
+    target = MINOR(cdi->dev);
+    
+    switch (cmd) {
     case CDROMREADMODE2:
        return -EINVAL;
     case CDROMREADMODE1:
-       return -EINVAL;
-       
-       /* block-copy from ../block/sbpcd.c with some adjustments... */
-    case CDROMMULTISESSION: /* tell start-of-last-session to user */
-    {
-       struct cdrom_multisession  ms_info;
-       long                       lba;
-       
-       err = verify_area(VERIFY_READ, (void *) arg,
-                         sizeof(struct cdrom_multisession));
-       if (err) return (err);
-       
-       copy_from_user(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
-       
-       if (ms_info.addr_format==CDROM_MSF) { /* MSF-bin requested */
-           lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET;
-           ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES);
-           lba %= CD_SECS*CD_FRAMES;
-           ms_info.addr.msf.second = lba / CD_FRAMES;
-           ms_info.addr.msf.frame  = lba % CD_FRAMES;
-       } else if (ms_info.addr_format==CDROM_LBA) /* lba requested */
-           ms_info.addr.lba=scsi_CDs[target].mpcd_sector;
-       else return (-EINVAL);
-       
-       ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01;
-       
-       err=verify_area(VERIFY_WRITE,(void *) arg,
-                       sizeof(struct cdrom_multisession));
-       if (err) return (err);
-       
-       copy_to_user((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
-       return (0);
-    }
+       return -EINVAL; 
        
     case BLKRAGET:
        if (!arg)
@@ -560,24+539,20 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        err = verify_area(VERIFY_WRITE, (int *) arg, sizeof(int));
        if (err)
                return err;
-       put_user(read_ahead[MAJOR(inode->i_rdev)], (int *) arg);
+       put_user(read_ahead[MAJOR(cdi->dev)], (int *) arg);
        return 0;
 
     case BLKRASET:
        if(!suser())
                return -EACCES;
-       if(!(inode->i_rdev))
+       if(!(cdi->dev))
                return -EINVAL;
        if(arg > 0xff)
                return -EINVAL;
-       read_ahead[MAJOR(inode->i_rdev)] = arg;
+       read_ahead[MAJOR(cdi->dev)] = arg;
        return 0;
 
-    RO_IOCTLS(dev,arg);
-
-    case CDROMRESET:
-       invalidate_buffers(inode->i_rdev);
-       return 0;
+    RO_IOCTLS(cdi->dev,arg);
 
     default:
        return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
new file mode 100644 (file)
index 0000000..3969ab4
--- /dev/null
@@ -0,0 +1,273 @@
+/* -*-linux-c-*-
+ *
+ * vendor-specific code for SCSI CD-ROM's goes here.
+ *
+ * This is needed becauce most of the new features (multisession and
+ * the like) are to new to be included into the SCSI-II standard (to
+ * be exact: there is'nt anything in my draft copy).
+ *
+ *   Gerd Knorr <kraxel@cs.tu-berlin.de> 
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+
+#include <linux/blk.h>
+#include "scsi.h"
+#include "hosts.h"
+#include <scsi/scsi_ioctl.h>
+
+#include <linux/cdrom.h>
+#include <linux/ucdrom.h>
+#include "sr.h"
+
+/* here are some constants to sort the vendors into groups */
+
+#define VENDOR_CAN_NOT_HANDLE  1   /* don't know how to handle */
+#define VENDOR_NEC             2
+#define VENDOR_TOSHIBA         3
+#define VENDOR_SONY_LIKE       4   /* much drives are Sony compatible */
+#define VENDOR_HP              5
+
+#define DEBUG
+
+void
+sr_vendor_init(int minor)
+{
+       char *vendor = scsi_CDs[minor].device->vendor;
+       char *model  = scsi_CDs[minor].device->model;
+               
+       if (!strncmp (vendor, "NEC", 3)) {
+               scsi_CDs[minor].vendor = VENDOR_NEC;
+               if (!strncmp (model,"CD-ROM DRIVE:25", 15) ||
+                   !strncmp (model,"CD-ROM DRIVE:36", 15)  ||
+                   !strncmp (model,"CD-ROM DRIVE:83", 15)  ||
+                   !strncmp (model,"CD-ROM DRIVE:84 ",16))
+                       /* these can't handle multisession, may hang */
+                       scsi_CDs[minor].cdi.mask |= CDC_MULTI_SESSION;
+
+       } else if (!strncmp (vendor, "TOSHIBA", 7)) {
+               scsi_CDs[minor].vendor = VENDOR_TOSHIBA;
+               
+       } else if (!strncmp (vendor, "HP", 2)) {
+               scsi_CDs[minor].vendor = VENDOR_HP;
+               
+       } else {
+               /* most drives can handled like sony ones, so we take
+                * it as default */
+               scsi_CDs[minor].vendor = VENDOR_SONY_LIKE;
+       }
+}
+
+
+
+/*
+ * support for XA/multisession-CD's
+ * 
+ *   - NEC:     Detection and support of multisession CD's.
+ *     
+ *   - TOSHIBA: Detection and support of multisession CD's.
+ *              Some XA-Sector tweaking, required for older drives.
+ *
+ *   - SONY:   Detection and support of multisession CD's.
+ *              added by Thomas Quinot <operator@melchior.cuivre.fdn.fr>
+ *
+ *   - PIONEER, HITACHI, PLEXTOR, MATSHITA: known to work with SONY code.
+ *
+ *   - HP:     Much like SONY, but a little different... (Thomas)
+ *              HP-Writers only ???
+ */
+
+#define BCD_TO_BIN(x)    ((((int)x & 0xf0) >> 4)*10 + ((int)x & 0x0f))
+
+int sr_cd_check(struct cdrom_device_info *cdi)
+{
+       unsigned long   sector,min,sec,frame;
+       unsigned char   *buffer;    /* the buffer for the ioctl */
+       unsigned char   cmd[12];    /* the scsi-command */
+       int             rc,is_xa,no_multi,minor;
+
+       minor = MINOR(cdi->dev);
+       
+       buffer = (unsigned char *) scsi_malloc(512);
+       if(!buffer) return -ENOMEM;
+       
+       sector   = 0;         /* the multisession sector offset goes here  */
+       is_xa    = 0;         /* flag: the CD uses XA-Sectors              */
+       no_multi = 0;         /* flag: the drive can't handle multisession */
+       rc       = 0;
+    
+       switch(scsi_CDs[minor].vendor) {
+       
+       case VENDOR_NEC:
+               memset(cmd,0,12);
+               cmd[0] = 0xde;
+               cmd[1] = (scsi_CDs[minor].device->lun << 5) | 0x03;
+               cmd[2] = 0xb0;
+               rc = sr_do_ioctl(minor, cmd, buffer, 0x16);
+               if (rc != 0)
+                       break;
+               if (buffer[14] != 0 && buffer[14] != 0xb0) {
+                       printk(KERN_INFO "sr (nec): Hmm, seems the cdrom doesn't support multisession CD's\n");
+                       no_multi = 1;
+                       break;
+               }
+               min    = BCD_TO_BIN(buffer[15]);
+               sec    = BCD_TO_BIN(buffer[16]);
+               frame  = BCD_TO_BIN(buffer[17]);
+               sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
+               is_xa  = (buffer[14] == 0xb0);
+               break;
+               
+       case VENDOR_TOSHIBA:
+               /* we request some disc information (is it a XA-CD ?,
+                * where starts the last session ?) */
+               memset(cmd,0,12);
+               cmd[0] = 0xc7;
+               cmd[1] = (scsi_CDs[minor].device->lun << 5) | 3;
+               rc = sr_do_ioctl(minor, cmd, buffer, 4);
+               if (rc == 0x28000002 &&
+                   !scsi_ioctl(scsi_CDs[minor].device,
+                               SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
+                       printk(KERN_INFO "sr (toshiba): Hmm, seems the drive doesn't support multisession CD's\n");
+                   no_multi = 1;
+                   break;
+               }
+               if (rc != 0)
+                       break;
+               min    = BCD_TO_BIN(buffer[1]);
+               sec    = BCD_TO_BIN(buffer[2]);
+               frame  = BCD_TO_BIN(buffer[3]);
+               sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
+               if (sector)
+                       sector -= CD_BLOCK_OFFSET;
+               is_xa  = (buffer[0] == 0x20);
+#if 0
+               /* this is required for some CD's:
+                *   - Enhanced-CD (Hardware tells wrong XA-flag)
+                *   - these broken non-XA multisession CD's
+                */
+               if (is_xa == 0 && sector != 0) {
+                       printk(KERN_WARNING "Warning: multisession offset "
+                              "found, setting XA-flag\n");
+                       is_xa = 1;
+               }
+#endif
+               /* now the XA-Sector tweaking: set_density... */
+               memset(cmd,0,12);
+               cmd[0] = MODE_SELECT;
+               cmd[1] = (scsi_CDs[minor].device->lun << 5)
+                       | (1 << 4);
+               cmd[4] = 12;
+               memset(buffer,0,12);
+               buffer[ 3] = 0x08;
+               buffer[ 4] = 0x83;
+               buffer[10] = 0x08;
+               rc = sr_do_ioctl(minor, cmd, buffer, 12);
+               if (rc != 0) {
+                       break;
+               }
+#if 0
+               /* shoult'nt be required any more */
+               scsi_CDs[minor].needs_sector_size = 1;
+#endif
+               break;
+
+       case VENDOR_HP:
+               cmd[0] = READ_TOC;
+               cmd[1] = (scsi_CDs[minor].device->lun << 5);
+               cmd[8] = 0x04;
+               cmd[9] = 0x40;
+               rc = sr_do_ioctl(minor, cmd, buffer, 12);       
+               if (rc != 0) {
+                       break;
+               }
+               if ((rc = buffer[2]) == 0) {
+                       printk (KERN_WARNING
+                               "sr (hp): No finished session\n");
+                       break;
+               }
+
+               cmd[0] = READ_TOC; /* Read TOC */
+               cmd[1] = (scsi_CDs[minor].device->lun << 5);
+               cmd[6] = rc & 0x7f;  /* number of last session */
+               cmd[8] = 0x0c;
+               cmd[9] = 0x40;
+               rc = sr_do_ioctl(minor, cmd, buffer, 12);       
+               if (rc != 0) {
+                       break;
+               }
+
+#undef STRICT_HP
+#ifdef STRICT_HP
+               sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16);
+               /* HP documentation states that Logical Start Address is
+                  returned as three (!) bytes, and that buffer[8] is
+                  reserved. This is strange, because a LBA usually is
+                  4 bytes long. */
+#else
+               sector = buffer[11] + (buffer[10] << 8) +
+                       (buffer[9] << 16) + (buffer[8] << 24);
+#endif
+               is_xa = !!sector;
+               break;
+
+       case VENDOR_SONY_LIKE:
+               /* Thomas QUINOT <thomas@melchior.cuivre.fdn.fr> */
+#ifdef DEBUG
+               printk(KERN_DEBUG
+                      "sr: use \"Sony group\" multisession code\n");
+#endif
+               memset(cmd,0,12);
+               cmd[0] = READ_TOC;
+               cmd[1] = (scsi_CDs[minor].device->lun << 5);
+               cmd[8] = 12;
+               cmd[9] = 0x40;
+               rc = sr_do_ioctl(minor, cmd, buffer, 12);       
+               if (rc != 0) {
+                       break;
+               }
+               if ((buffer[0] << 8) + buffer[1] != 0x0a) {
+                       printk(KERN_INFO "sr (sony): Hmm, seems the drive doesn't support multisession CD's\n");
+                       no_multi = 1;
+                       break;
+               }
+               sector = buffer[11] + (buffer[10] << 8) +
+                       (buffer[9] << 16) + (buffer[8] << 24);
+               if (buffer[6] <= 1) {
+                       /* ignore sector offsets from first track */
+                       sector = 0;
+               }
+               is_xa = !!sector;
+               break;
+               
+       case VENDOR_CAN_NOT_HANDLE:
+               sector = 0;
+               no_multi = 1;
+               break;
+
+       default:
+               /* should not happen */
+               printk(KERN_WARNING
+                      "sr: unknown vendor code (%i), not initialized ?\n",
+                      scsi_CDs[minor].vendor);
+               sector = 0;
+               no_multi = 1;
+               break;
+       }
+    
+#ifdef DEBUG
+       if (sector)
+               printk(KERN_DEBUG
+                      "sr: multisession CD detected, offset: %lu\n",sector);
+#endif
+
+       scsi_CDs[minor].ms_offset = sector;
+       scsi_CDs[minor].xa_flag = is_xa;
+       if (no_multi)
+               cdi->mask |= CDC_MULTI_SESSION;
+       
+       scsi_free(buffer, 512);
+
+       return rc;
+}
index 8087c84..b7fabab 100644 (file)
@@ -144,20+144,14 @@ unsigned long * create_elf_tables(char *p, int argc, int envc,
        __put_user((unsigned long)argc,--sp);
        current->mm->arg_start = (unsigned long) p;
        while (argc-->0) {
-               char c;
                __put_user(p,argv++);
-               do {
-                       get_user(c,p++);
-               } while (c);
+               p += strlen_user(p);
        }
        __put_user(NULL, argv);
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
        while (envc-->0) {
-               char c;
                __put_user(p,envp++);
-               do {
-                       get_user(c,p++);
-               } while (c);
+               p += strlen_user(p);
        }
        __put_user(NULL, envp);
        current->mm->env_end = (unsigned long) p;
index c7f915c..043e35b 100644 (file)
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/bitops.h>
 
 #define NR_SIZES 5
 static char buffersize_index[17] =
@@ -169,7+170,7 @@ repeat:
           there to be dirty buffers on any of the other lists. */
                bh = lru_list[BUF_DIRTY];
                if (!bh)
-                       break;
+                       goto repeat2;
                for (i = nr_buffers_type[BUF_DIRTY]*2 ; i-- > 0 ; bh = next) {
                        if (bh->b_list != BUF_DIRTY)
                                goto repeat;
@@ -1865,6+1866,32 @@ unsigned long generate_cluster(kdev_t dev, int b[], int size)
                 return reassign_cluster(dev, b[0], size);
 }
 
+unsigned long generate_cluster_swab32(kdev_t dev, int b[], int size)
+{
+       int i, offset;
+       
+       for (i = 0, offset = 0 ; offset < PAGE_SIZE ; i++, offset += size) {
+               if(i && le32_to_cpu(b[i])-1 !=
+                  le32_to_cpu(b[i-1])) return 0;  /* No need to cluster */
+               if(find_buffer(dev, le32_to_cpu(b[i]), size)) return 0;
+       };
+
+       /* OK, we have a candidate for a new cluster */
+       
+       /* See if one size of buffer is over-represented in the buffer cache,
+          if so reduce the numbers of buffers */
+       if(maybe_shrink_lav_buffers(size))
+        {
+                int retval;
+                retval = try_to_generate_cluster(dev, le32_to_cpu(b[0]), size);
+                if(retval) return retval;
+        };
+       
+       if (nr_free_pages > min_free_pages*2) 
+                return try_to_generate_cluster(dev, le32_to_cpu(b[0]), size);
+       else
+                return reassign_cluster(dev, le32_to_cpu(b[0]), size);
+}
 
 /* ===================== Init ======================= */
 
index 7e75f0c..560e387 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -178,27+178,23 @@ asmlinkage int sys_uselib(const char * library)
 
 /*
  * count() counts the number of arguments/envelopes
- *
- * We also do some limited EFAULT checking: this isn't complete, but
- * it does cover most cases. I'll have to do this correctly some day..
  */
 static int count(char ** argv)
 {
-       int error, i = 0;
-       char ** tmp, *p;
+       int i = 0;
 
-       if ((tmp = argv) != NULL) {
-               error = verify_area(VERIFY_READ, tmp, sizeof(char *));
-               if (error)
-                       return error;
+       if (argv != NULL) {
                for (;;) {
-                       get_user(p,tmp++);
+                       char * p;
+                       int error;
+
+                       error = get_user(p,argv);
+                       if (error)
+                               return error;
                        if (!p)
                                break;
+                       argv++;
                        i++;
-                       error = verify_area(VERIFY_READ, p, 1);
-                       if (error)
-                               return error;
                }
        }
        return i;
@@ -224,60+220,51 @@ static int count(char ** argv)
 unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
                unsigned long p, int from_kmem)
 {
-       char *tmp, *tmp1, *pag = NULL;
-       int len, offset = 0;
-       unsigned long old_fs, new_fs;
+       char *str;
+       unsigned long old_fs;
 
        if (!p)
                return 0;       /* bullet-proofing */
-       new_fs = get_ds();
        old_fs = get_fs();
        if (from_kmem==2)
-               set_fs(new_fs);
+               set_fs(KERNEL_DS);
        while (argc-- > 0) {
+               int len;
+               unsigned long pos;
+
                if (from_kmem == 1)
-                       set_fs(new_fs);
-               get_user(tmp, argv+argc);
-               if (!tmp)
+                       set_fs(KERNEL_DS);
+               get_user(str, argv+argc);
+               if (!str)
                        panic("VFS: argc is wrong");
-               tmp1 = tmp;
                if (from_kmem == 1)
                        set_fs(old_fs);
-               for (;;) {
-                       char c;
-                       get_user(c,tmp++);
-                       if (!c)
-                               break;
-               }
-               len = tmp - tmp1;
+               len = strlen_user(str); /* includes the '\0' */
                if (p < len) {  /* this shouldn't happen - 128kB */
                        set_fs(old_fs);
                        return 0;
                }
+               p -= len;
+               pos = p;
                while (len) {
-                       --p; --tmp; --len;
-                       if (--offset < 0) {
-                               offset = p % PAGE_SIZE;
+                       char *pag;
+                       int offset, bytes_to_copy;
+
+                       offset = pos % PAGE_SIZE;
+                       if (!(pag = (char *) page[pos/PAGE_SIZE]) &&
+                           !(pag = (char *) page[pos/PAGE_SIZE] =
+                             (unsigned long *) get_free_page(GFP_USER))) {
                                if (from_kmem==2)
                                        set_fs(old_fs);
-                               if (!(pag = (char *) page[p/PAGE_SIZE]) &&
-                                   !(pag = (char *) page[p/PAGE_SIZE] =
-                                     (unsigned long *) get_free_page(GFP_USER))) 
-                                       return 0;
-                               if (from_kmem==2)
-                                       set_fs(new_fs);
-
-                       }
-                       if (len == 0 || offset == 0)
-                               get_user(*(pag + offset), tmp);
-                       else {
-                         int bytes_to_copy = (len > offset) ? offset : len;
-                         tmp -= bytes_to_copy;
-                         p -= bytes_to_copy;
-                         offset -= bytes_to_copy;
-                         len -= bytes_to_copy;
-                         copy_from_user(pag + offset, tmp, bytes_to_copy + 1);
+                               return 0;
                        }
+                       bytes_to_copy = PAGE_SIZE - offset;
+                       if (bytes_to_copy > len)
+                               bytes_to_copy = len;
+                       copy_from_user(pag + offset, str, bytes_to_copy);
+                       pos += bytes_to_copy;
+                       str += bytes_to_copy;
+                       len -= bytes_to_copy;
                }
        }
        if (from_kmem==2)
index 1e0b69e..61b5b1a 100644 (file)
@@ -7,6+7,8 @@
  * Universite Pierre et Marie Curie (Paris VI)
  *
  *  Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 /*
 #include <linux/locks.h>
 
 #include <asm/bitops.h>
+#include <asm/byteorder.h>
 
 #define in_range(b, first, len)                ((b) >= (first) && (b) <= (first) + (len) - 1)
 
@@ -71,12+74,12 @@ static void read_block_bitmap (struct super_block * sb,
        struct buffer_head * bh;
        
        gdp = get_group_desc (sb, block_group, NULL);
-       bh = bread (sb->s_dev, gdp->bg_block_bitmap, sb->s_blocksize);
+       bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize);
        if (!bh)
                ext2_panic (sb, "read_block_bitmap",
                            "Cannot read block bitmap - "
                            "block_group = %d, block_bitmap = %lu",
-                           block_group, (unsigned long) gdp->bg_block_bitmap);
+                           block_group, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
        sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
        sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
 }
@@ -185,8+188,8 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
        }
        lock_super (sb);
        es = sb->u.ext2_sb.s_es;
-       if (block < es->s_first_data_block || 
-           (block + count) > es->s_blocks_count) {
+       if (block < le32_to_cpu(es->s_first_data_block) || 
+           (block + count) > le32_to_cpu(es->s_blocks_count)) {
                ext2_error (sb, "ext2_free_blocks",
                            "Freeing blocks not in datazone - "
                            "block = %lu, count = %lu", block, count);
@@ -196,9+199,9 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
 
        ext2_debug ("freeing block %lu\n", block);
 
-       block_group = (block - es->s_first_data_block) /
+       block_group = (block - le32_to_cpu(es->s_first_data_block)) /
                      EXT2_BLOCKS_PER_GROUP(sb);
-       bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
+       bit = (block - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb);
        if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
                ext2_panic (sb, "ext2_free_blocks",
                            "Freeing blocks across group boundary - "
@@ -209,11+212,11 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
        gdp = get_group_desc (sb, block_group, &bh2);
 
        if (test_opt (sb, CHECK_STRICT) &&
-           (in_range (gdp->bg_block_bitmap, block, count) ||
-            in_range (gdp->bg_inode_bitmap, block, count) ||
-            in_range (block, gdp->bg_inode_table,
+           (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
+            in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
+            in_range (block, le32_to_cpu(gdp->bg_inode_table),
                       sb->u.ext2_sb.s_itb_per_group) ||
-            in_range (block + count - 1, gdp->bg_inode_table,
+            in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
                       sb->u.ext2_sb.s_itb_per_group)))
                ext2_panic (sb, "ext2_free_blocks",
                            "Freeing blocks in system zones - "
@@ -221,15+224,17 @@ void ext2_free_blocks (const struct inode * inode, unsigned long block,
                            block, count);
 
        for (i = 0; i < count; i++) {
-               if (!clear_bit (bit + i, bh->b_data))
+               if (!ext2_clear_bit (bit + i, bh->b_data))
                        ext2_warning (sb, "ext2_free_blocks",
                                      "bit already cleared for block %lu", 
                                      block);
                else {
                        if (sb->dq_op)
                                sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize));
-                       gdp->bg_free_blocks_count++;
-                       es->s_free_blocks_count++;
+                       gdp->bg_free_blocks_count =
+                               cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
+                       es->s_free_blocks_count =
+                               cpu_to_le32(le32_to_cpu(es->s_free_blocks_count)+1);
                }
        }
        
@@ -276,7+281,7 @@ int ext2_new_block (const struct inode * inode, unsigned long goal,
        }
        lock_super (sb);
        es = sb->u.ext2_sb.s_es;
-       if (es->s_free_blocks_count <= es->s_r_blocks_count &&
+       if (le32_to_cpu(es->s_free_blocks_count) <= le32_to_cpu(es->s_r_blocks_count) &&
            (!fsuser() && (sb->u.ext2_sb.s_resuid != current->fsuid) &&
             (sb->u.ext2_sb.s_resgid == 0 ||
              !in_group_p (sb->u.ext2_sb.s_resgid)))) {
@@ -290,12+295,13 @@ repeat:
        /*
         * First, test whether the goal block is free.
         */
-       if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
-               goal = es->s_first_data_block;
-       i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
+       if (goal < le32_to_cpu(es->s_first_data_block) ||
+           goal >= le32_to_cpu(es->s_blocks_count))
+               goal = le32_to_cpu(es->s_first_data_block);
+       i = (goal - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb);
        gdp = get_group_desc (sb, i, &bh2);
-       if (gdp->bg_free_blocks_count > 0) {
-               j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
+       if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
+               j = ((goal - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb));
 #ifdef EXT2FS_DEBUG
                if (j)
                        goal_attempts++;
@@ -305,7+311,7 @@ repeat:
 
                ext2_debug ("goal is at %d:%d.\n", i, j);
 
-               if (!test_bit(j, bh->b_data)) {
+               if (!ext2_test_bit(j, bh->b_data)) {
 #ifdef EXT2FS_DEBUG
                        goal_hits++;
                        ext2_debug ("goal bit allocated.\n");
@@ -322,7+328,7 @@ repeat:
                         * next 64-bit boundary is simple..
                         */
                        int end_goal = (j + 63) & ~63;
-                       j = find_next_zero_bit(bh->b_data, end_goal, j);
+                       j = ext2_find_next_zero_bit(bh->b_data, end_goal, j);
                        if (j < end_goal)
                                goto got_block;
                }
@@ -345,7+351,8 @@ repeat:
                        j = k;
                        goto search_back;
                }
-               k = find_next_zero_bit ((unsigned long *) bh->b_data, 
+
+               k = ext2_find_next_zero_bit ((unsigned long *) bh->b_data, 
                                        EXT2_BLOCKS_PER_GROUP(sb),
                                        j);
                if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
@@ -365,7+372,7 @@ repeat:
                if (i >= sb->u.ext2_sb.s_groups_count)
                        i = 0;
                gdp = get_group_desc (sb, i, &bh2);
-               if (gdp->bg_free_blocks_count > 0)
+               if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
                        break;
        }
        if (k >= sb->u.ext2_sb.s_groups_count) {
@@ -379,7+386,7 @@ repeat:
        if (j < EXT2_BLOCKS_PER_GROUP(sb))
                goto search_back;
        else
-               j = find_first_zero_bit ((unsigned long *) bh->b_data,
+               j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
                                         EXT2_BLOCKS_PER_GROUP(sb));
        if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
                ext2_error (sb, "ext2_new_block",
@@ -394,7+401,7 @@ search_back:
         * bitmap.  Now search backwards up to 7 bits to find the
         * start of this group of free blocks.
         */
-       for (k = 0; k < 7 && j > 0 && !test_bit (j - 1, bh->b_data); k++, j--);
+       for (k = 0; k < 7 && j > 0 && !ext2_test_bit (j - 1, bh->b_data); k++, j--);
        
 got_block:
 
@@ -410,17+417,17 @@ got_block:
                        return 0;
                }
 
-       tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + es->s_first_data_block;
+       tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block);
 
        if (test_opt (sb, CHECK_STRICT) &&
-           (tmp == gdp->bg_block_bitmap ||
-            tmp == gdp->bg_inode_bitmap ||
-            in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
+           (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
+            tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
+            in_range (tmp, le32_to_cpu(gdp->bg_inode_table), sb->u.ext2_sb.s_itb_per_group)))
                ext2_panic (sb, "ext2_new_block",
                            "Allocating block in system zone - "
                            "block = %u", tmp);
 
-       if (set_bit (j, bh->b_data)) {
+       if (ext2_set_bit (j, bh->b_data)) {
                ext2_warning (sb, "ext2_new_block",
                              "bit already set for block %d", j);
                if (sb->dq_op)
@@ -442,15+449,19 @@ got_block:
                        if (sb->dq_op)
                                if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)))
                                        break;
-                       if (set_bit (j + k, bh->b_data)) {
+                       if (ext2_set_bit (j + k, bh->b_data)) {
                                if (sb->dq_op)
                                        sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize));
-                               break;
+                               break;
                        }
                        (*prealloc_count)++;
                }       
-               gdp->bg_free_blocks_count -= *prealloc_count;
-               es->s_free_blocks_count -= *prealloc_count;
+               gdp->bg_free_blocks_count =
+                       cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -
+                              *prealloc_count);
+               es->s_free_blocks_count =
+                       cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) -
+                              *prealloc_count);
                ext2_debug ("Preallocated a further %lu bits.\n",
                            *prealloc_count);
        }
@@ -464,7+475,7 @@ got_block:
                wait_on_buffer (bh);
        }
 
-       if (j >= es->s_blocks_count) {
+       if (j >= le32_to_cpu(es->s_blocks_count)) {
                ext2_error (sb, "ext2_new_block",
                            "block >= blocks count - "
                            "block_group = %d, block=%d", i, j);
@@ -484,9+495,9 @@ got_block:
        ext2_debug ("allocating block %d. "
                    "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
 
-       gdp->bg_free_blocks_count--;
+       gdp->bg_free_blocks_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1);
        mark_buffer_dirty(bh2, 1);
-       es->s_free_blocks_count--;
+       es->s_free_blocks_count = cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1);
        mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        sb->s_dirt = 1;
        unlock_super (sb);
@@ -510,20+521,20 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
        gdp = NULL;
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
                gdp = get_group_desc (sb, i, NULL);
-               desc_count += gdp->bg_free_blocks_count;
+               desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
                bitmap_nr = load_block_bitmap (sb, i);
                x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
                                     sb->s_blocksize);
                printk ("group %d: stored = %d, counted = %lu\n",
-                       i, gdp->bg_free_blocks_count, x);
+                       i, le16_to_cpu(gdp->bg_free_blocks_count), x);
                bitmap_count += x;
        }
        printk("ext2_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
-              es->s_free_blocks_count, desc_count, bitmap_count);
+              le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
        unlock_super (sb);
        return bitmap_count;
 #else
-       return sb->u.ext2_sb.s_es->s_free_blocks_count;
+       return le32_to_cpu(sb->u.ext2_sb.s_es->s_free_blocks_count);
 #endif
 }
 
@@ -531,7+542,7 @@ static inline int block_in_use (unsigned long block,
                                struct super_block * sb,
                                unsigned char * map)
 {
-       return test_bit ((block - sb->u.ext2_sb.s_es->s_first_data_block) %
+       return ext2_test_bit ((block - le32_to_cpu(sb->u.ext2_sb.s_es->s_first_data_block)) %
                         EXT2_BLOCKS_PER_GROUP(sb), map);
 }
 
@@ -554,48+565,48 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
                      EXT2_DESC_PER_BLOCK(sb);
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
                gdp = get_group_desc (sb, i, NULL);
-               desc_count += gdp->bg_free_blocks_count;
+               desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
                bitmap_nr = load_block_bitmap (sb, i);
                bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
-               if (!test_bit (0, bh->b_data))
+               if (!ext2_test_bit (0, bh->b_data))
                        ext2_error (sb, "ext2_check_blocks_bitmap",
                                    "Superblock in group %d is marked free", i);
 
                for (j = 0; j < desc_blocks; j++)
-                       if (!test_bit (j + 1, bh->b_data))
+                       if (!ext2_test_bit (j + 1, bh->b_data))
                                ext2_error (sb, "ext2_check_blocks_bitmap",
                                            "Descriptor block #%d in group "
                                            "%d is marked free", j, i);
 
-               if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
+               if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))
                        ext2_error (sb, "ext2_check_blocks_bitmap",
                                    "Block bitmap for group %d is marked free",
                                    i);
 
-               if (!block_in_use (gdp->bg_inode_bitmap, sb, bh->b_data))
+               if (!block_in_use (le32_to_cpu(gdp->bg_inode_bitmap), sb, bh->b_data))
                        ext2_error (sb, "ext2_check_blocks_bitmap",
                                    "Inode bitmap for group %d is marked free",
                                    i);
 
                for (j = 0; j < sb->u.ext2_sb.s_itb_per_group; j++)
-                       if (!block_in_use (gdp->bg_inode_table + j, sb, bh->b_data))
+                       if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, sb, bh->b_data))
                                ext2_error (sb, "ext2_check_blocks_bitmap",
                                            "Block #%d of the inode table in "
                                            "group %d is marked free", j, i);
 
                x = ext2_count_free (bh, sb->s_blocksize);
-               if (gdp->bg_free_blocks_count != x)
+               if (le16_to_cpu(gdp->bg_free_blocks_count) != x)
                        ext2_error (sb, "ext2_check_blocks_bitmap",
                                    "Wrong free blocks count for group %d, "
                                    "stored = %d, counted = %lu", i,
-                                   gdp->bg_free_blocks_count, x);
+                                   le16_to_cpu(gdp->bg_free_blocks_count), x);
                bitmap_count += x;
        }
-       if (es->s_free_blocks_count != bitmap_count)
+       if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count)
                ext2_error (sb, "ext2_check_blocks_bitmap",
                            "Wrong free blocks count in super block, "
                            "stored = %lu, counted = %lu",
-                           (unsigned long) es->s_free_blocks_count, bitmap_count);
+                           (unsigned long) le32_to_cpu(es->s_free_blocks_count), bitmap_count);
        unlock_super (sb);
 }
index 195fbf3..7de729e 100644 (file)
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  ext2 directory handling functions
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 #include <asm/uaccess.h>
@@ -77,23+80,24 @@ int ext2_check_dir_entry (const char * function, struct inode * dir,
 {
        const char * error_msg = NULL;
 
-       if (de->rec_len < EXT2_DIR_REC_LEN(1))
+       if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1))
                error_msg = "rec_len is smaller than minimal";
-       else if (de->rec_len % 4 != 0)
+       else if (le16_to_cpu(de->rec_len) % 4 != 0)
                error_msg = "rec_len % 4 != 0";
-       else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len))
+       else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)))
                error_msg = "rec_len is too small for name_len";
-       else if (dir && ((char *) de - bh->b_data) + de->rec_len >
+       else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) >
                 dir->i_sb->s_blocksize)
                error_msg = "directory entry across blocks";
-       else if (dir && de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count)
+       else if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count))
                error_msg = "inode out of bounds";
 
        if (error_msg != NULL)
                ext2_error (dir->i_sb, function, "bad entry in directory #%lu: %s - "
                            "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
-                           dir->i_ino, error_msg, offset, (unsigned long) de->inode,
-                           de->rec_len, de->name_len);
+                           dir->i_ino, error_msg, offset,
+                           (unsigned long) le32_to_cpu(de->inode),
+                           le16_to_cpu(de->rec_len), le16_to_cpu(de->name_len));
        return error_msg == NULL ? 1 : 0;
 }
 
@@ -161,9+165,9 @@ revalidate:
                                 * least that it is non-zero.  A
                                 * failure will be detected in the
                                 * dirent test below. */
-                               if (de->rec_len < EXT2_DIR_REC_LEN(1))
+                               if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1))
                                        break;
-                               i += de->rec_len;
+                               i += le16_to_cpu(de->rec_len);
                        }
                        offset = i;
                        filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
@@ -183,8+187,8 @@ revalidate:
                                brelse (bh);
                                return stored;
                        }
-                       offset += de->rec_len;
-                       if (de->inode) {
+                       offset += le16_to_cpu(de->rec_len);
+                       if (le32_to_cpu(de->inode)) {
                                /* We might block in the next section
                                 * if the data destination is
                                 * currently swapped out.  So, use a
@@ -192,16+196,17 @@ revalidate:
                                 * not the directory has been modified
                                 * during the copy operation. */
                                unsigned long version;
-                               dcache_add(inode, de->name, de->name_len, de->inode);
+                               dcache_add(inode, de->name, le16_to_cpu(de->name_len),
+                                          le32_to_cpu(de->inode));
                                version = inode->i_version;
-                               error = filldir(dirent, de->name, de->name_len, filp->f_pos, de->inode);
+                               error = filldir(dirent, de->name, le16_to_cpu(de->name_len), filp->f_pos, le32_to_cpu(de->inode));
                                if (error)
                                        break;
                                if (version != inode->i_version)
                                        goto revalidate;
                                stored ++;
                        }
-                       filp->f_pos += de->rec_len;
+                       filp->f_pos += le16_to_cpu(de->rec_len);
                }
                offset = 0;
                brelse (bh);
index e9c1e28..1d608d0 100644 (file)
  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
  * 
  *  ext2fs fsync primitive
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 #include <asm/uaccess.h>
 #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
 #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
 
-static int sync_block (struct inode * inode, u32 * block, int wait)
+static __inline__ int sync_block (struct inode * inode, u32 * block, int wait)
 {
        struct buffer_head * bh;
        int tmp;
@@ -55,7+58,35 @@ static int sync_block (struct inode * inode, u32 * block, int wait)
        return 0;
 }
 
-static int sync_iblock (struct inode * inode, u32 * iblock, 
+static __inline__ int sync_block_swab32 (struct inode * inode, u32 * block, int wait)
+{
+       struct buffer_head * bh;
+       int tmp;
+       
+       if (!le32_to_cpu(*block))
+               return 0;
+       tmp = le32_to_cpu(*block);
+       bh = get_hash_table (inode->i_dev, le32_to_cpu(*block), blocksize);
+       if (!bh)
+               return 0;
+       if (le32_to_cpu(*block) != tmp) {
+               brelse (bh);
+               return 1;
+       }
+       if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
+               brelse (bh);
+               return -1;
+       }
+       if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
+               brelse (bh);
+               return 0;
+       }
+       ll_rw_block (WRITE, 1, &bh);
+       bh->b_count--;
+       return 0;
+}
+
+static __inline__ int sync_iblock (struct inode * inode, u32 * iblock, 
                        struct buffer_head ** bh, int wait) 
 {
        int rc, tmp;
@@ -78,8+109,31 @@ static int sync_iblock (struct inode * inode, u32 * iblock,
        return 0;
 }
 
+static __inline__ int sync_iblock_swab32 (struct inode * inode, u32 * iblock, 
+                              struct buffer_head ** bh, int wait) 
+{
+       int rc, tmp;
+       
+       *bh = NULL;
+       tmp = le32_to_cpu(*iblock);
+       if (!tmp)
+               return 0;
+       rc = sync_block_swab32 (inode, iblock, wait);
+       if (rc)
+               return rc;
+       *bh = bread (inode->i_dev, tmp, blocksize);
+       if (tmp != le32_to_cpu(*iblock)) {
+               brelse (*bh);
+               *bh = NULL;
+               return 1;
+       }
+       if (!*bh)
+               return -1;
+       return 0;
+}
+
 
-static int sync_direct (struct inode * inode, int wait)
+static __inline__ int sync_direct (struct inode * inode, int wait)
 {
        int i;
        int rc, err = 0;
@@ -94,7+148,7 @@ static int sync_direct (struct inode * inode, int wait)
        return err;
 }
 
-static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
+static __inline__ int sync_indirect (struct inode * inode, u32 * iblock, int wait)
 {
        int i;
        struct buffer_head * ind_bh;
@@ -105,9+159,9 @@ static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
                return rc;
        
        for (i = 0; i < addr_per_block; i++) {
-               rc = sync_block (inode, 
-                                ((u32 *) ind_bh->b_data) + i,
-                                wait);
+               rc = sync_block_swab32 (inode, 
+                                       ((u32 *) ind_bh->b_data) + i,
+                                       wait);
                if (rc > 0)
                        break;
                if (rc)
@@ -117,7+171,30 @@ static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
        return err;
 }
 
-static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
+static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock, int wait)
+{
+       int i;
+       struct buffer_head * ind_bh;
+       int rc, err = 0;
+
+       rc = sync_iblock_swab32 (inode, iblock, &ind_bh, wait);
+       if (rc || !ind_bh)
+               return rc;
+       
+       for (i = 0; i < addr_per_block; i++) {
+               rc = sync_block_swab32 (inode, 
+                                       ((u32 *) ind_bh->b_data) + i,
+                                       wait);
+               if (rc > 0)
+                       break;
+               if (rc)
+                       err = rc;
+       }
+       brelse (ind_bh);
+       return err;
+}
+
+static __inline__ int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
 {
        int i;
        struct buffer_head * dind_bh;
@@ -128,9+205,32 @@ static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
                return rc;
        
        for (i = 0; i < addr_per_block; i++) {
-               rc = sync_indirect (inode,
-                                   ((u32 *) dind_bh->b_data) + i,
-                                   wait);
+               rc = sync_indirect_swab32 (inode,
+                                          ((u32 *) dind_bh->b_data) + i,
+                                          wait);
+               if (rc > 0)
+                       break;
+               if (rc)
+                       err = rc;
+       }
+       brelse (dind_bh);
+       return err;
+}
+
+static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock, int wait)
+{
+       int i;
+       struct buffer_head * dind_bh;
+       int rc, err = 0;
+
+       rc = sync_iblock_swab32 (inode, diblock, &dind_bh, wait);
+       if (rc || !dind_bh)
+               return rc;
+       
+       for (i = 0; i < addr_per_block; i++) {
+               rc = sync_indirect_swab32 (inode,
+                                          ((u32 *) dind_bh->b_data) + i,
+                                          wait);
                if (rc > 0)
                        break;
                if (rc)
@@ -140,7+240,7 @@ static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
        return err;
 }
 
-static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
+static __inline__ int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
 {
        int i;
        struct buffer_head * tind_bh;
@@ -151,9+251,9 @@ static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
                return rc;
        
        for (i = 0; i < addr_per_block; i++) {
-               rc = sync_dindirect (inode,
-                                    ((u32 *) tind_bh->b_data) + i,
-                                    wait);
+               rc = sync_dindirect_swab32 (inode,
+                                           ((u32 *) tind_bh->b_data) + i,
+                                           wait);
                if (rc > 0)
                        break;
                if (rc)
index 35435d4..27a0626 100644 (file)
@@ -8,6+8,8 @@
  *
  *  BSD ufs-inspired inode and directory allocation by 
  *  Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 /*
 #include <linux/locks.h>
 
 #include <asm/bitops.h>
+#include <asm/byteorder.h>
 
 static struct ext2_group_desc * get_group_desc (struct super_block * sb,
                                                unsigned int block_group,
@@ -70,12+73,12 @@ static void read_inode_bitmap (struct super_block * sb,
        struct buffer_head * bh;
 
        gdp = get_group_desc (sb, block_group, NULL);
-       bh = bread (sb->s_dev, gdp->bg_inode_bitmap, sb->s_blocksize);
+       bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
        if (!bh)
                ext2_panic (sb, "read_inode_bitmap",
                            "Cannot read inode bitmap - "
                            "block_group = %lu, inode_bitmap = %lu",
-                           block_group, (unsigned long) gdp->bg_inode_bitmap);
+                           block_group, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
        sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
        sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
 }
@@ -188,7+191,7 @@ void ext2_free_inode (struct inode * inode)
        sb = inode->i_sb;
        lock_super (sb);
        if (inode->i_ino < EXT2_FIRST_INO(sb) ||
-           inode->i_ino > sb->u.ext2_sb.s_es->s_inodes_count) {
+           inode->i_ino > le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count)) {
                ext2_error (sb, "free_inode",
                            "reserved inode or nonexistent inode");
                unlock_super (sb);
@@ -199,16+202,19 @@ void ext2_free_inode (struct inode * inode)
        bit = (inode->i_ino - 1) % EXT2_INODES_PER_GROUP(sb);
        bitmap_nr = load_inode_bitmap (sb, block_group);
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
-       if (!clear_bit (bit, bh->b_data))
+       if (!ext2_clear_bit (bit, bh->b_data))
                ext2_warning (sb, "ext2_free_inode",
                              "bit already cleared for inode %lu", inode->i_ino);
        else {
                gdp = get_group_desc (sb, block_group, &bh2);
-               gdp->bg_free_inodes_count++;
+               gdp->bg_free_inodes_count =
+                       cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
                if (S_ISDIR(inode->i_mode))
-                       gdp->bg_used_dirs_count--;
+                       gdp->bg_used_dirs_count =
+                               cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
                mark_buffer_dirty(bh2, 1);
-               es->s_free_inodes_count++;
+               es->s_free_inodes_count =
+                       cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                inode->i_dirt = 0;
        }
@@ -273,14+279,14 @@ repeat:
        
        *err = -ENOSPC;
        if (S_ISDIR(mode)) {
-               avefreei = es->s_free_inodes_count /
+               avefreei = le32_to_cpu(es->s_free_inodes_count) /
                        sb->u.ext2_sb.s_groups_count;
 /* I am not yet convinced that this next bit is necessary.
                i = dir->u.ext2_i.i_block_group;
                for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
                        tmp = get_group_desc (sb, i, &bh2);
-                       if ((tmp->bg_used_dirs_count << 8) < 
-                           tmp->bg_free_inodes_count) {
+                       if ((le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
+                           le16_to_cpu(tmp->bg_free_inodes_count)) {
                                gdp = tmp;
                                break;
                        }
@@ -291,11+297,11 @@ repeat:
                if (!gdp) {
                        for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
                                tmp = get_group_desc (sb, j, &bh2);
-                               if (tmp->bg_free_inodes_count &&
-                                       tmp->bg_free_inodes_count >= avefreei) {
+                               if (le16_to_cpu(tmp->bg_free_inodes_count) &&
+                                       le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
                                        if (!gdp || 
-                                           (tmp->bg_free_blocks_count >
-                                            gdp->bg_free_blocks_count)) {
+                                           (le16_to_cpu(tmp->bg_free_blocks_count) >
+                                            le16_to_cpu(gdp->bg_free_blocks_count))) {
                                                i = j;
                                                gdp = tmp;
                                        }
@@ -310,7+316,7 @@ repeat:
                 */
                i = dir->u.ext2_i.i_block_group;
                tmp = get_group_desc (sb, i, &bh2);
-               if (tmp->bg_free_inodes_count)
+               if (le16_to_cpu(tmp->bg_free_inodes_count))
                        gdp = tmp;
                else
                {
@@ -323,7+329,7 @@ repeat:
                                if (i >= sb->u.ext2_sb.s_groups_count)
                                        i -= sb->u.ext2_sb.s_groups_count;
                                tmp = get_group_desc (sb, i, &bh2);
-                               if (tmp->bg_free_inodes_count) {
+                               if (le16_to_cpu(tmp->bg_free_inodes_count)) {
                                        gdp = tmp;
                                        break;
                                }
@@ -338,7+344,7 @@ repeat:
                                if (++i >= sb->u.ext2_sb.s_groups_count)
                                        i = 0;
                                tmp = get_group_desc (sb, i, &bh2);
-                               if (tmp->bg_free_inodes_count) {
+                               if (le16_to_cpu(tmp->bg_free_inodes_count)) {
                                        gdp = tmp;
                                        break;
                                }
@@ -353,10+359,10 @@ repeat:
        }
        bitmap_nr = load_inode_bitmap (sb, i);
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
-       if ((j = find_first_zero_bit ((unsigned long *) bh->b_data,
+       if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
                                      EXT2_INODES_PER_GROUP(sb))) <
            EXT2_INODES_PER_GROUP(sb)) {
-               if (set_bit (j, bh->b_data)) {
+               if (ext2_set_bit (j, bh->b_data)) {
                        ext2_warning (sb, "ext2_new_inode",
                                      "bit already set for inode %d", j);
                        goto repeat;
@@ -367,7+373,7 @@ repeat:
                        wait_on_buffer (bh);
                }
        } else {
-               if (gdp->bg_free_inodes_count != 0) {
+               if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
                        ext2_error (sb, "ext2_new_inode",
                                    "Free inodes count corrupted in group %d",
                                    i);
@@ -378,7+384,7 @@ repeat:
                goto repeat;
        }
        j += i * EXT2_INODES_PER_GROUP(sb) + 1;
-       if (j < EXT2_FIRST_INO(sb) || j > es->s_inodes_count) {
+       if (j < EXT2_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
                ext2_error (sb, "ext2_new_inode",
                            "reserved inode or inode > inodes count - "
                            "block_group = %d,inode=%d", i, j);
@@ -386,11+392,14 @@ repeat:
                iput (inode);
                return NULL;
        }
-       gdp->bg_free_inodes_count--;
+       gdp->bg_free_inodes_count =
+               cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
        if (S_ISDIR(mode))
-               gdp->bg_used_dirs_count++;
+               gdp->bg_used_dirs_count =
+                       cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
        mark_buffer_dirty(bh2, 1);
-       es->s_free_inodes_count--;
+       es->s_free_inodes_count =
+               cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
        mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        sb->s_dirt = 1;
        inode->i_mode = mode;
@@ -463,20+472,20 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
        gdp = NULL;
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
                gdp = get_group_desc (sb, i, NULL);
-               desc_count += gdp->bg_free_inodes_count;
+               desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
                bitmap_nr = load_inode_bitmap (sb, i);
                x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
                                     EXT2_INODES_PER_GROUP(sb) / 8);
                printk ("group %d: stored = %d, counted = %lu\n",
-                       i, gdp->bg_free_inodes_count, x);
+                       i, le16_to_cpu(gdp->bg_free_inodes_count), x);
                bitmap_count += x;
        }
        printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
-               es->s_free_inodes_count, desc_count, bitmap_count);
+               le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
        unlock_super (sb);
        return desc_count;
 #else
-       return sb->u.ext2_sb.s_es->s_free_inodes_count;
+       return le32_to_cpu(sb->u.ext2_sb.s_es->s_free_inodes_count);
 #endif
 }
 
@@ -495,21+504,22 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
        gdp = NULL;
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
                gdp = get_group_desc (sb, i, NULL);
-               desc_count += gdp->bg_free_inodes_count;
+               desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
                bitmap_nr = load_inode_bitmap (sb, i);
                x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
                                     EXT2_INODES_PER_GROUP(sb) / 8);
-               if (gdp->bg_free_inodes_count != x)
+               if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
                        ext2_error (sb, "ext2_check_inodes_bitmap",
                                    "Wrong free inodes count in group %d, "
                                    "stored = %d, counted = %lu", i,
-                                   gdp->bg_free_inodes_count, x);
+                                   le16_to_cpu(gdp->bg_free_inodes_count), x);
                bitmap_count += x;
        }
-       if (es->s_free_inodes_count != bitmap_count)
+       if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
                ext2_error (sb, "ext2_check_inodes_bitmap",
                            "Wrong free inodes count in super block, "
                            "stored = %lu, counted = %lu",
-                           (unsigned long) es->s_free_inodes_count, bitmap_count);
+                           (unsigned long) le32_to_cpu(es->s_free_inodes_count),
+                           bitmap_count);
        unlock_super (sb);
 }
index 85f17d0..eddcc5a 100644 (file)
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 #include <asm/uaccess.h>
@@ -52,7+54,7 @@ static inline int block_bmap (struct buffer_head * bh, int nr)
 
        if (!bh)
                return 0;
-       tmp = ((u32 *) bh->b_data)[nr];
+       tmp = le32_to_cpu(((u32 *) bh->b_data)[nr]);
        brelse (bh);
        return tmp;
 }
@@ -115,7+117,7 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int * err
                ext2_debug ("preallocation miss (%lu/%lu).\n",
                            alloc_hits, ++alloc_attempts);
                if (S_ISREG(inode->i_mode))
-                       result = ext2_new_block (inode, goal,
+                       result = ext2_new_block (inode, goal, 
                                 &inode->u.ext2_i.i_prealloc_count,
                                 &inode->u.ext2_i.i_prealloc_block, err);
                else
@@ -224,7+226,7 @@ repeat:
                if (!goal)
                        goal = (inode->u.ext2_i.i_block_group * 
                                EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +
-                              inode->i_sb->u.ext2_sb.s_es->s_first_data_block;
+                              le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_first_data_block);
        }
 
        ext2_debug ("goal = %d.\n", goal);
@@ -272,10+274,10 @@ static struct buffer_head * block_getblk (struct inode * inode,
        }
        p = (u32 *) bh->b_data + nr;
 repeat:
-       tmp = *p;
+       tmp = le32_to_cpu(*p);
        if (tmp) {
                result = getblk (bh->b_dev, tmp, blocksize);
-               if (tmp == *p) {
+               if (tmp == le32_to_cpu(*p)) {
                        brelse (bh);
                        return result;
                }
@@ -293,8+295,8 @@ repeat:
                goal = inode->u.ext2_i.i_next_alloc_goal;
        if (!goal) {
                for (tmp = nr - 1; tmp >= 0; tmp--) {
-                       if (((u32 *) bh->b_data)[tmp]) {
-                               goal = ((u32 *)bh->b_data)[tmp];
+                       if (le32_to_cpu(((u32 *) bh->b_data)[tmp])) {
+                               goal = le32_to_cpu(((u32 *)bh->b_data)[tmp]);
                                break;
                        }
                }
@@ -307,12+309,12 @@ repeat:
                return NULL;
        }
        result = getblk (bh->b_dev, tmp, blocksize);
-       if (*p) {
+       if (le32_to_cpu(*p)) {
                ext2_free_blocks (inode, tmp, 1);
                brelse (result);
                goto repeat;
        }
-       *p = tmp;
+       *p = le32_to_cpu(tmp);
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
                ll_rw_block (WRITE, 1, &bh);
@@ -348,15+350,15 @@ static int block_getcluster (struct inode * inode, struct buffer_head * bh,
          p = (u32 *) bh->b_data + nr + i;
          
          /* All blocks in cluster must already be allocated */
-         if(*p == 0) goto out;
+         if(le32_to_cpu(*p) == 0) goto out;
          
          /* See if aligned correctly */
-         if(i==0) firstblock = *p;
-         else if(*p != firstblock + i) goto out;
+         if(i==0) firstblock = le32_to_cpu(*p);
+         else if(le32_to_cpu(*p) != firstblock + i) goto out;
        }
        
        p = (u32 *) bh->b_data + nr;
-       result = generate_cluster(bh->b_dev, (int *) p, blocksize);
+       result = generate_cluster_swab32(bh->b_dev, (int *) p, blocksize);
 
       out:
        brelse(bh);
@@ -506,7+508,7 @@ void ext2_read_inode (struct inode * inode)
        if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
             inode->i_ino != EXT2_ACL_DATA_INO &&
             inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
-           inode->i_ino > inode->i_sb->u.ext2_sb.s_es->s_inodes_count) {
+           inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
                ext2_error (inode->i_sb, "ext2_read_inode",
                            "bad inode number: %lu", inode->i_ino);
                return;
@@ -527,7+529,7 @@ void ext2_read_inode (struct inode * inode)
         */
        offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *
                EXT2_INODE_SIZE(inode->i_sb);
-       block = gdp[desc].bg_inode_table +
+       block = le32_to_cpu(gdp[desc].bg_inode_table) +
                (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
        if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
                ext2_panic (inode->i_sb, "ext2_read_inode",
@@ -536,27+538,27 @@ void ext2_read_inode (struct inode * inode)
        offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
-       inode->i_mode = raw_inode->i_mode;
-       inode->i_uid = raw_inode->i_uid;
-       inode->i_gid = raw_inode->i_gid;
-       inode->i_nlink = raw_inode->i_links_count;
-       inode->i_size = raw_inode->i_size;
-       inode->i_atime = raw_inode->i_atime;
-       inode->i_ctime = raw_inode->i_ctime;
-       inode->i_mtime = raw_inode->i_mtime;
-       inode->u.ext2_i.i_dtime = raw_inode->i_dtime;
+       inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+       inode->i_uid = le16_to_cpu(raw_inode->i_uid);
+       inode->i_gid = le16_to_cpu(raw_inode->i_gid);
+       inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+       inode->i_size = le32_to_cpu(raw_inode->i_size);
+       inode->i_atime = le32_to_cpu(raw_inode->i_atime);
+       inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
+       inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
+       inode->u.ext2_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
        inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
-       inode->i_blocks = raw_inode->i_blocks;
+       inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
        inode->i_version = ++event;
        inode->u.ext2_i.i_new_inode = 0;
-       inode->u.ext2_i.i_flags = raw_inode->i_flags;
-       inode->u.ext2_i.i_faddr = raw_inode->i_faddr;
+       inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags);
+       inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
        inode->u.ext2_i.i_frag_no = raw_inode->i_frag;
        inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
        inode->u.ext2_i.i_osync = 0;
-       inode->u.ext2_i.i_file_acl = raw_inode->i_file_acl;
-       inode->u.ext2_i.i_dir_acl = raw_inode->i_dir_acl;
-       inode->u.ext2_i.i_version = raw_inode->i_version;
+       inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
+       inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+       inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);
        inode->u.ext2_i.i_block_group = block_group;
        inode->u.ext2_i.i_next_alloc_block = 0;
        inode->u.ext2_i.i_next_alloc_goal = 0;
@@ -564,9+566,12 @@ void ext2_read_inode (struct inode * inode)
                ext2_error (inode->i_sb, "ext2_read_inode",
                            "New inode has non-zero prealloc count!");
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-               inode->i_rdev = to_kdev_t(raw_inode->i_block[0]);
+               inode->i_rdev = to_kdev_t(le32_to_cpu(raw_inode->i_block[0]));
+       else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
+               for (block = 0; block < EXT2_N_BLOCKS; block++)
+                       inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
        else for (block = 0; block < EXT2_N_BLOCKS; block++)
-               inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
+               inode->u.ext2_i.i_data[block] = le32_to_cpu(raw_inode->i_block[block]);
        brelse (bh);
        inode->i_op = NULL;
        if (inode->i_ino == EXT2_ACL_IDX_INO ||
@@ -606,7+611,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
 
        if ((inode->i_ino != EXT2_ROOT_INO &&
             inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
-           inode->i_ino > inode->i_sb->u.ext2_sb.s_es->s_inodes_count) {
+           inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
                ext2_error (inode->i_sb, "ext2_write_inode",
                            "bad inode number: %lu", inode->i_ino);
                return 0;
@@ -627,7+632,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
         */
        offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *
                EXT2_INODE_SIZE(inode->i_sb);
-       block = gdp[desc].bg_inode_table +
+       block = le32_to_cpu(gdp[desc].bg_inode_table) +
                (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
        if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
                ext2_panic (inode->i_sb, "ext2_write_inode",
@@ -636,27+641,30 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
        offset &= EXT2_BLOCK_SIZE(inode->i_sb) - 1;
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
-       raw_inode->i_mode = inode->i_mode;
-       raw_inode->i_uid = inode->i_uid;
-       raw_inode->i_gid = inode->i_gid;
-       raw_inode->i_links_count = inode->i_nlink;
-       raw_inode->i_size = inode->i_size;
-       raw_inode->i_atime = inode->i_atime;
-       raw_inode->i_ctime = inode->i_ctime;
-       raw_inode->i_mtime = inode->i_mtime;
-       raw_inode->i_blocks = inode->i_blocks;
-       raw_inode->i_dtime = inode->u.ext2_i.i_dtime;
-       raw_inode->i_flags = inode->u.ext2_i.i_flags;
-       raw_inode->i_faddr = inode->u.ext2_i.i_faddr;
+       raw_inode->i_mode = cpu_to_le16(inode->i_mode);
+       raw_inode->i_uid = cpu_to_le16(inode->i_uid);
+       raw_inode->i_gid = cpu_to_le16(inode->i_gid);
+       raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
+       raw_inode->i_size = cpu_to_le32(inode->i_size);
+       raw_inode->i_atime = cpu_to_le32(inode->i_atime);
+       raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
+       raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
+       raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
+       raw_inode->i_dtime = cpu_to_le32(inode->u.ext2_i.i_dtime);
+       raw_inode->i_flags = cpu_to_le32(inode->u.ext2_i.i_flags);
+       raw_inode->i_faddr = cpu_to_le32(inode->u.ext2_i.i_faddr);
        raw_inode->i_frag = inode->u.ext2_i.i_frag_no;
        raw_inode->i_fsize = inode->u.ext2_i.i_frag_size;
-       raw_inode->i_file_acl = inode->u.ext2_i.i_file_acl;
-       raw_inode->i_dir_acl = inode->u.ext2_i.i_dir_acl;
-       raw_inode->i_version = inode->u.ext2_i.i_version;
+       raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl);
+       raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
+       raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version);
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-               raw_inode->i_block[0] = kdev_t_to_nr(inode->i_rdev);
+               raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
+       else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
+               for (block = 0; block < EXT2_N_BLOCKS; block++)
+                       raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
        else for (block = 0; block < EXT2_N_BLOCKS; block++)
-               raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
+               raw_inode->i_block[block] = cpu_to_le32(inode->u.ext2_i.i_data[block]);
        mark_buffer_dirty(bh, 1);
        inode->i_dirt = 0;
        if (do_sync) {
index 2249eb1..632d6ee 100644 (file)
  *  linux/fs/minix/namei.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 #include <asm/uaccess.h>
 static int ext2_match (int len, const char * const name,
                       struct ext2_dir_entry * de)
 {
-       if (!de || !de->inode || len > EXT2_NAME_LEN)
+       if (!de || !le32_to_cpu(de->inode) || len > EXT2_NAME_LEN)
                return 0;
        /*
         * "" means "." ---> so paths like "/usr/lib//libc.a" work
         */
-       if (!len && de->name_len == 1 && (de->name[0] == '.') &&
+       if (!len && le16_to_cpu(de->name_len) == 1 && (de->name[0] == '.') &&
           (de->name[1] == '\0'))
                return 1;
-       if (len != de->name_len)
+       if (len != le16_to_cpu(de->name_len))
                return 0;
        return !memcmp(name, de->name, len);
 }
@@ -121,7+124,7 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
                        if (!ext2_check_dir_entry ("ext2_find_entry", dir,
                                                   de, bh, offset))
                                goto failure;
-                       if (de->inode != 0 && ext2_match (namelen, name, de)) {
+                       if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) {
                                for (i = 0; i < NAMEI_RA_SIZE; ++i) {
                                        if (bh_use[i] != bh)
                                                brelse (bh_use[i]);
@@ -129,9+132,9 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
                                *res_dir = de;
                                return bh;
                        }
-                       offset += de->rec_len;
+                       offset += le16_to_cpu(de->rec_len);
                        de = (struct ext2_dir_entry *)
-                               ((char *) de + de->rec_len);
+                               ((char *) de + le16_to_cpu(de->rec_len));
                }
 
                brelse (bh);
@@ -188,7+191,7 @@ int ext2_lookup (struct inode * dir, const char * name, int len,
                iput (dir);
                return -ENOENT;
        }
-       ino = de->inode;
+       ino = le32_to_cpu(de->inode);
        dcache_add(dir, name, len, ino);
        brelse (bh);
        if (!(*result = iget (dir->i_sb, ino))) {
@@ -265,8+268,8 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                                ext2_debug ("creating next block\n");
 
                                de = (struct ext2_dir_entry *) bh->b_data;
-                               de->inode = 0;
-                               de->rec_len = sb->s_blocksize;
+                               de->inode = le32_to_cpu(0);
+                               de->rec_len = le16_to_cpu(sb->s_blocksize);
                                dir->i_size = offset + sb->s_blocksize;
                                dir->i_dirt = 1;
                        } else {
@@ -282,24+285,24 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                        brelse (bh);
                        return NULL;
                }
-               if (de->inode != 0 && ext2_match (namelen, name, de)) {
+               if (le32_to_cpu(de->inode) != 0 && ext2_match (namelen, name, de)) {
                                *err = -EEXIST;
                                brelse (bh);
                                return NULL;
                }
-               if ((de->inode == 0 && de->rec_len >= rec_len) ||
-                   (de->rec_len >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
-                       offset += de->rec_len;
-                       if (de->inode) {
+               if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
+                   (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)) + rec_len)) {
+                       offset += le16_to_cpu(de->rec_len);
+                       if (le32_to_cpu(de->inode)) {
                                de1 = (struct ext2_dir_entry *) ((char *) de +
-                                       EXT2_DIR_REC_LEN(de->name_len));
-                               de1->rec_len = de->rec_len -
-                                       EXT2_DIR_REC_LEN(de->name_len);
-                               de->rec_len = EXT2_DIR_REC_LEN(de->name_len);
+                                       EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+                               de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) -
+                                       EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
+                               de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
                                de = de1;
                        }
-                       de->inode = 0;
-                       de->name_len = namelen;
+                       de->inode = cpu_to_le32(0);
+                       de->name_len = cpu_to_le16(namelen);
                        memcpy (de->name, name, namelen);
                        /*
                         * XXX shouldn't update any times until successful
@@ -320,8+323,8 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                        *err = 0;
                        return bh;
                }
-               offset += de->rec_len;
-               de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
+               offset += le16_to_cpu(de->rec_len);
+               de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        brelse (bh);
        return NULL;
@@ -346,13+349,15 @@ static int ext2_delete_entry (struct ext2_dir_entry * dir,
                        return -EIO;
                if (de == dir)  {
                        if (pde)
-                               pde->rec_len += dir->rec_len;
-                       dir->inode = 0;
+                               pde->rec_len =
+                                       cpu_to_le16(le16_to_cpu(pde->rec_len) +
+                                                   le16_to_cpu(dir->rec_len));
+                       dir->inode = le32_to_cpu(0);
                        return 0;
                }
-               i += de->rec_len;
+               i += le16_to_cpu(de->rec_len);
                pde = de;
-               de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
+               de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        return -ENOENT;
 }
@@ -384,9+389,9 @@ int ext2_create (struct inode * dir,const char * name, int len, int mode,
                iput (dir);
                return err;
        }
-       de->inode = inode->i_ino;
+       de->inode = cpu_to_le32(inode->i_ino);
        dir->i_version = ++event;
-       dcache_add(dir, de->name, de->name_len, de->inode);
+       dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
@@ -453,9+458,9 @@ int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
                iput (dir);
                return err;
        }
-       de->inode = inode->i_ino;
+       de->inode = cpu_to_le32(inode->i_ino);
        dir->i_version = ++event;
-       dcache_add(dir, de->name, de->name_len, de->inode);
+       dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
@@ -507,14+512,14 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
        }
        inode->i_blocks = inode->i_sb->s_blocksize / 512;
        de = (struct ext2_dir_entry *) dir_block->b_data;
-       de->inode = inode->i_ino;
-       de->name_len = 1;
-       de->rec_len = EXT2_DIR_REC_LEN(de->name_len);
+       de->inode = cpu_to_le32(inode->i_ino);
+       de->name_len = cpu_to_le16(1);
+       de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(le16_to_cpu(de->name_len)));
        strcpy (de->name, ".");
-       de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
-       de->inode = dir->i_ino;
-       de->rec_len = inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1);
-       de->name_len = 2;
+       de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+       de->inode = cpu_to_le32(dir->i_ino);
+       de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
+       de->name_len = cpu_to_le16(2);
        strcpy (de->name, "..");
        inode->i_nlink = 2;
        mark_buffer_dirty(dir_block, 1);
@@ -531,9+536,9 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
                iput (inode);
                return err;
        }
-       de->inode = inode->i_ino;
+       de->inode = cpu_to_le32(inode->i_ino);
        dir->i_version = ++event;
-       dcache_add(dir, de->name, de->name_len, de->inode);
+       dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
@@ -567,16+572,16 @@ static int empty_dir (struct inode * inode)
                return 1;
        }
        de = (struct ext2_dir_entry *) bh->b_data;
-       de1 = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
-       if (de->inode != inode->i_ino || !de1->inode || 
+       de1 = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+       if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || 
            strcmp (".", de->name) || strcmp ("..", de1->name)) {
                ext2_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no `.' or `..'",
                              inode->i_ino);
                return 1;
        }
-       offset = de->rec_len + de1->rec_len;
-       de = (struct ext2_dir_entry *) ((char *) de1 + de1->rec_len);
+       offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+       de = (struct ext2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len));
        while (offset < inode->i_size ) {
                if ((void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
                        brelse (bh);
@@ -595,12+600,12 @@ static int empty_dir (struct inode * inode)
                        brelse (bh);
                        return 1;
                }
-               if (de->inode) {
+               if (le32_to_cpu(de->inode)) {
                        brelse (bh);
                        return 0;
                }
-               offset += de->rec_len;
-               de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
+               offset += le16_to_cpu(de->rec_len);
+               de = (struct ext2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        brelse (bh);
        return 1;
@@ -626,7+631,7 @@ repeat:
        if (!bh)
                goto end_rmdir;
        retval = -EPERM;
-       if (!(inode = iget (dir->i_sb, de->inode)))
+       if (!(inode = iget (dir->i_sb, le32_to_cpu(de->inode))))
                goto end_rmdir;
        if (inode->i_sb->dq_op)
                inode->i_sb->dq_op->initialize (inode, -1);
@@ -634,7+639,7 @@ repeat:
                retval = -EBUSY;
                goto end_rmdir;
        }
-       if (de->inode != inode->i_ino) {
+       if (le32_to_cpu(de->inode) != inode->i_ino) {
                iput(inode);
                brelse(bh);
                current->counter = 0;
@@ -654,7+659,7 @@ repeat:
        down(&inode->i_sem);
        if (!empty_dir (inode))
                retval = -ENOTEMPTY;
-       else if (de->inode != inode->i_ino)
+       else if (le32_to_cpu(de->inode) != inode->i_ino)
                retval = -ENOENT;
        else {
                if (inode->i_count > 1) {
@@ -714,7+719,7 @@ repeat:
        bh = ext2_find_entry (dir, name, len, &de);
        if (!bh)
                goto end_unlink;
-       if (!(inode = iget (dir->i_sb, de->inode)))
+       if (!(inode = iget (dir->i_sb, le32_to_cpu(de->inode))))
                goto end_unlink;
        if (inode->i_sb->dq_op)
                inode->i_sb->dq_op->initialize (inode, -1);
@@ -723,7+728,7 @@ repeat:
                goto end_unlink;
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                goto end_unlink;
-       if (de->inode != inode->i_ino) {
+       if (le32_to_cpu(de->inode) != inode->i_ino) {
                iput(inode);
                brelse(bh);
                current->counter = 0;
@@ -829,9+834,9 @@ int ext2_symlink (struct inode * dir, const char * name, int len,
                iput (dir);
                return err;
        }
-       de->inode = inode->i_ino;
+       de->inode = cpu_to_le32(inode->i_ino);
        dir->i_version = ++event;
-       dcache_add(dir, de->name, de->name_len, de->inode);
+       dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
@@ -878,9+883,9 @@ int ext2_link (struct inode * oldinode, struct inode * dir,
                iput (oldinode);
                return err;
        }
-       de->inode = oldinode->i_ino;
+       de->inode = cpu_to_le32(oldinode->i_ino);
        dir->i_version = ++event;
-       dcache_add(dir, de->name, de->name_len, de->inode);
+       dcache_add(dir, de->name, le16_to_cpu(de->name_len), le32_to_cpu(de->inode));
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
@@ -921,11+926,11 @@ static int subdir (struct inode * new_inode, struct inode * old_inode)
 
 #define PARENT_INO(buffer) \
        ((struct ext2_dir_entry *) ((char *) buffer + \
-       ((struct ext2_dir_entry *) buffer)->rec_len))->inode
+       le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
 
 #define PARENT_NAME(buffer) \
        ((struct ext2_dir_entry *) ((char *) buffer + \
-       ((struct ext2_dir_entry *) buffer)->rec_len))->name
+       le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->name
 
 /*
  * rename uses retrying to avoid race-conditions: at least they should be
@@ -973,7+978,7 @@ start_up:
        retval = -ENOENT;
        if (!old_bh)
                goto end_rename;
-       old_inode = __iget (old_dir->i_sb, old_de->inode, 0); /* don't cross mnt-points */
+       old_inode = __iget (old_dir->i_sb, le32_to_cpu(old_de->inode), 0); /* don't cross mnt-points */
        if (!old_inode)
                goto end_rename;
        if (must_be_dir && !S_ISDIR(old_inode->i_mode))
@@ -987,7+992,7 @@ start_up:
                goto end_rename;
        new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de);
        if (new_bh) {
-               new_inode = __iget (new_dir->i_sb, new_de->inode, 0); /* no mntp cross */
+               new_inode = __iget (new_dir->i_sb, le32_to_cpu(new_de->inode), 0); /* no mntp cross */
                if (!new_inode) {
                        brelse (new_bh);
                        new_bh = NULL;
@@ -1029,7+1034,7 @@ start_up:
                dir_bh = ext2_bread (old_inode, 0, 0, &retval);
                if (!dir_bh)
                        goto end_rename;
-               if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
+               if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
                        goto end_rename;
                retval = -EMLINK;
                if (!new_inode && new_dir->i_nlink >= EXT2_LINK_MAX)
@@ -1044,17+1049,17 @@ start_up:
        /*
         * sanity checking before doing the rename - avoid races
         */
-       if (new_inode && (new_de->inode != new_inode->i_ino))
+       if (new_inode && (le32_to_cpu(new_de->inode) != new_inode->i_ino))
                goto try_again;
-       if (new_de->inode && !new_inode)
+       if (le32_to_cpu(new_de->inode) && !new_inode)
                goto try_again;
-       if (old_de->inode != old_inode->i_ino)
+       if (le32_to_cpu(old_de->inode) != old_inode->i_ino)
                goto try_again;
        /*
         * ok, that's it
         */
-       new_de->inode = old_inode->i_ino;
-       dcache_add(new_dir, new_de->name, new_de->name_len, new_de->inode);
+       new_de->inode = le32_to_cpu(old_inode->i_ino);
+       dcache_add(new_dir, new_de->name, le16_to_cpu(new_de->name_len), le32_to_cpu(new_de->inode));
        retval = ext2_delete_entry (old_de, old_bh);
        if (retval == -ENOENT)
                goto try_again;
@@ -1069,7+1074,7 @@ start_up:
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
        old_dir->i_dirt = 1;
        if (dir_bh) {
-               PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
+               PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
                dcache_add(old_inode, "..", 2, new_dir->i_ino);
                mark_buffer_dirty(dir_bh, 1);
                old_dir->i_nlink--;
index e9e5b90..6bcdb5e 100644 (file)
  *  linux/fs/minix/inode.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 #include <linux/module.h>
@@ -39,7+42,8 @@ void ext2_error (struct super_block * sb, const char * function,
 
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
-               sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
+               sb->u.ext2_sb.s_es->s_state =
+                       cpu_to_le16(le16_to_cpu(sb->u.ext2_sb.s_es->s_state) | EXT2_ERROR_FS);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
        }
@@ -47,14+51,14 @@ void ext2_error (struct super_block * sb, const char * function,
        vsprintf (error_buf, fmt, args);
        va_end (args);
        if (test_opt (sb, ERRORS_PANIC) ||
-           (sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_PANIC &&
+           (le16_to_cpu(sb->u.ext2_sb.s_es->s_errors) == EXT2_ERRORS_PANIC &&
             !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_RO)))
                panic ("EXT2-fs panic (device %s): %s: %s\n",
                       kdevname(sb->s_dev), function, error_buf);
        printk (KERN_CRIT "EXT2-fs error (device %s): %s: %s\n",
                kdevname(sb->s_dev), function, error_buf);
        if (test_opt (sb, ERRORS_RO) ||
-           (sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_RO &&
+           (le16_to_cpu(sb->u.ext2_sb.s_es->s_errors) == EXT2_ERRORS_RO &&
             !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_PANIC))) {
                printk ("Remounting filesystem read-only\n");
                sb->s_flags |= MS_RDONLY;
@@ -68,7+72,8 @@ NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
 
        if (!(sb->s_flags & MS_RDONLY)) {
                sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
-               sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
+               sb->u.ext2_sb.s_es->s_state =
+                       cpu_to_le16(le16_to_cpu(sb->u.ext2_sb.s_es->s_state) | EXT2_ERROR_FS);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
        }
@@ -102,7+107,7 @@ void ext2_put_super (struct super_block * sb)
 
        lock_super (sb);
        if (!(sb->s_flags & MS_RDONLY)) {
-               sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
+               sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        }
        sb->s_dev = 0;
@@ -270,7+275,7 @@ static int parse_options (char * options, unsigned long * sb_block,
 static void ext2_setup_super (struct super_block * sb,
                              struct ext2_super_block * es)
 {
-       if (es->s_rev_level > EXT2_MAX_SUPP_REV) {
+       if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {
                        printk ("EXT2-fs warning: revision level too high, "
                                "forcing read/only mode\n");
                        sb->s_flags |= MS_RDONLY;
@@ -282,19+287,20 @@ static void ext2_setup_super (struct super_block * sb,
                else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS))
                        printk ("EXT2-fs warning: mounting fs with errors, "
                                "running e2fsck is recommended\n");
-               else if (es->s_max_mnt_count >= 0 &&
-                        es->s_mnt_count >= (unsigned short) es->s_max_mnt_count)
+               else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
+                        le16_to_cpu(es->s_mnt_count) >=
+                        (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
                        printk ("EXT2-fs warning: maximal mount count reached, "
                                "running e2fsck is recommended\n");
-               else if (es->s_checkinterval &&
-                       (es->s_lastcheck + es->s_checkinterval <= CURRENT_TIME))
+               else if (le32_to_cpu(es->s_checkinterval) &&
+                       (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
                        printk ("EXT2-fs warning: checktime reached, "
                                "running e2fsck is recommended\n");
-               es->s_state &= ~EXT2_VALID_FS;
-               if (!es->s_max_mnt_count)
-                       es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
-               es->s_mnt_count++;
-               es->s_mtime = CURRENT_TIME;
+               es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS);
+               if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
+                       es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
+               es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
+               es->s_mtime = cpu_to_le32(CURRENT_TIME);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
                if (test_opt (sb, DEBUG))
@@ -317,7+323,7 @@ static int ext2_check_descriptors (struct super_block * sb)
 {
        int i;
        int desc_block = 0;
-       unsigned long block = sb->u.ext2_sb.s_es->s_first_data_block;
+       unsigned long block = le32_to_cpu(sb->u.ext2_sb.s_es->s_first_data_block);
        struct ext2_group_desc * gdp = NULL;
 
        ext2_debug ("Checking group descriptors");
@@ -326,32+332,32 @@ static int ext2_check_descriptors (struct super_block * sb)
        {
                if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext2_group_desc *) sb->u.ext2_sb.s_group_desc[desc_block++]->b_data;
-               if (gdp->bg_block_bitmap < block ||
-                   gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
+                   le32_to_cpu(gdp->bg_block_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Block bitmap for group %d"
                                    " not in group (block %lu)!",
-                                   i, (unsigned long) gdp->bg_block_bitmap);
+                                   i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
                        return 0;
                }
-               if (gdp->bg_inode_bitmap < block ||
-                   gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
+                   le32_to_cpu(gdp->bg_inode_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Inode bitmap for group %d"
                                    " not in group (block %lu)!",
-                                   i, (unsigned long) gdp->bg_inode_bitmap);
+                                   i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
                        return 0;
                }
-               if (gdp->bg_inode_table < block ||
-                   gdp->bg_inode_table + sb->u.ext2_sb.s_itb_per_group >=
+               if (le32_to_cpu(gdp->bg_inode_table) < block ||
+                   le32_to_cpu(gdp->bg_inode_table) + sb->u.ext2_sb.s_itb_per_group >=
                    block + EXT2_BLOCKS_PER_GROUP(sb))
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Inode table for group %d"
                                    " not in group (block %lu)!",
-                                   i, (unsigned long) gdp->bg_inode_table);
+                                   i, (unsigned long) le32_to_cpu(gdp->bg_inode_table));
                        return 0;
                }
                block += EXT2_BLOCKS_PER_GROUP(sb);
@@ -399,7+405,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
         */
        es = (struct ext2_super_block *) bh->b_data;
        sb->u.ext2_sb.s_es = es;
-       sb->s_magic = es->s_magic;
+       sb->s_magic = le16_to_cpu(es->s_magic);
        if (sb->s_magic != EXT2_SUPER_MAGIC) {
                if (!silent)
                        printk ("VFS: Can't find an ext2 filesystem on dev "
@@ -412,22+418,22 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                MOD_DEC_USE_COUNT;
                return NULL;
        }
-       if (es->s_rev_level > EXT2_GOOD_OLD_REV) {
-               if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) {
+       if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
+               if (le32_to_cpu(es->s_feature_incompat) & ~EXT2_FEATURE_INCOMPAT_SUPP) {
                        printk("EXT2-fs: %s: couldn't mount because of "
                               "unsupported optional features.\n", 
                               kdevname(dev));
                        goto failed_mount;
                }
                if (!(sb->s_flags & MS_RDONLY) &&
-                   (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
+                   (le32_to_cpu(es->s_feature_ro_compat) & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
                        printk("EXT2-fs: %s: couldn't mount RDWR because of "
                               "unsupported optional features.\n", 
                               kdevname(dev));
                        goto failed_mount;
                }
        }
-       sb->s_blocksize_bits = sb->u.ext2_sb.s_es->s_log_block_size + 10;
+       sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10;
        sb->s_blocksize = 1 << sb->s_blocksize_bits;
        if (sb->s_blocksize != BLOCK_SIZE && 
            (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||  
@@ -446,17+452,17 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                }
                es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
                sb->u.ext2_sb.s_es = es;
-               if (es->s_magic != EXT2_SUPER_MAGIC) {
+               if (es->s_magic != le16_to_cpu(EXT2_SUPER_MAGIC)) {
                        printk ("EXT2-fs: Magic mismatch, very weird !\n");
                        goto failed_mount;
                }
        }
-       if (es->s_rev_level == EXT2_GOOD_OLD_REV) {
+       if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
                sb->u.ext2_sb.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
                sb->u.ext2_sb.s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
        } else {
-               sb->u.ext2_sb.s_inode_size = es->s_inode_size;
-               sb->u.ext2_sb.s_first_ino = es->s_first_ino;
+               sb->u.ext2_sb.s_inode_size = le16_to_cpu(es->s_inode_size);
+               sb->u.ext2_sb.s_first_ino = le32_to_cpu(es->s_first_ino);
                if (sb->u.ext2_sb.s_inode_size != EXT2_GOOD_OLD_INODE_SIZE) {
                        printk ("EXT2-fs: unsupported inode size: %d\n",
                                sb->u.ext2_sb.s_inode_size);
@@ -464,15+470,15 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                }
        }
        sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
-                                  es->s_log_frag_size;
+                                  (__s32) le32_to_cpu(es->s_log_frag_size);
        if (sb->u.ext2_sb.s_frag_size)
                sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
                                                  sb->u.ext2_sb.s_frag_size;
        else
                sb->s_magic = 0;
-       sb->u.ext2_sb.s_blocks_per_group = es->s_blocks_per_group;
-       sb->u.ext2_sb.s_frags_per_group = es->s_frags_per_group;
-       sb->u.ext2_sb.s_inodes_per_group = es->s_inodes_per_group;
+       sb->u.ext2_sb.s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
+       sb->u.ext2_sb.s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
+       sb->u.ext2_sb.s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
        sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
                                           EXT2_INODE_SIZE(sb);
        sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
@@ -483,12+489,12 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
        if (resuid != EXT2_DEF_RESUID)
                sb->u.ext2_sb.s_resuid = resuid;
        else
-               sb->u.ext2_sb.s_resuid = es->s_def_resuid;
+               sb->u.ext2_sb.s_resuid = le16_to_cpu(es->s_def_resuid);
        if (resgid != EXT2_DEF_RESGID)
                sb->u.ext2_sb.s_resgid = resgid;
        else
-               sb->u.ext2_sb.s_resgid = es->s_def_resgid;
-       sb->u.ext2_sb.s_mount_state = es->s_state;
+               sb->u.ext2_sb.s_resgid = le16_to_cpu(es->s_def_resgid);
+       sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
        sb->u.ext2_sb.s_rename_lock = 0;
        sb->u.ext2_sb.s_rename_wait = NULL;
        sb->u.ext2_sb.s_addr_per_block_bits =
@@ -531,8+537,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                goto failed_mount;
        }
 
-       sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
-                                       es->s_first_data_block +
+       sb->u.ext2_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+                                       le32_to_cpu(es->s_first_data_block) +
                                       EXT2_BLOCKS_PER_GROUP(sb) - 1) /
                                       EXT2_BLOCKS_PER_GROUP(sb);
        db_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
@@ -596,7+602,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
 static void ext2_commit_super (struct super_block * sb,
                               struct ext2_super_block * es)
 {
-       es->s_wtime = CURRENT_TIME;
+       es->s_wtime = cpu_to_le32(CURRENT_TIME);
        mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
        sb->s_dirt = 0;
 }
@@ -621,9+627,9 @@ void ext2_write_super (struct super_block * sb)
 
                ext2_debug ("setting valid to 0\n");
 
-               if (es->s_state & EXT2_VALID_FS) {
-                       es->s_state &= ~EXT2_VALID_FS;
-                       es->s_mtime = CURRENT_TIME;
+               if (le16_to_cpu(es->s_state) & EXT2_VALID_FS) {
+                       es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS);
+                       es->s_mtime = cpu_to_le32(CURRENT_TIME);
                }
                ext2_commit_super (sb, es);
        }
@@ -653,15+659,15 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
        if (*flags & MS_RDONLY) {
-               if (es->s_state & EXT2_VALID_FS ||
+               if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
                    !(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
                        return 0;
                /*
                 * OK, we are remounting a valid rw partition rdonly, so set
                 * the rdonly flag and then mark the partition as valid again.
                 */
-               es->s_state = sb->u.ext2_sb.s_mount_state;
-               es->s_mtime = CURRENT_TIME;
+               es->s_state = cpu_to_le16(sb->u.ext2_sb.s_mount_state);
+               es->s_mtime = cpu_to_le32(CURRENT_TIME);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
                sb->s_dirt = 1;
                ext2_commit_super (sb, es);
@@ -672,7+678,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
                 * store the current valid flag.  (It may have been changed 
                 * by e2fsck since we originally mounted the partition.)
                 */
-               sb->u.ext2_sb.s_mount_state = es->s_state;
+               sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
                sb->s_flags &= ~MS_RDONLY;
                ext2_setup_super (sb, es);
        }
@@ -722,18+728,18 @@ void ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
                                     1 /* block bitmap */ +
                                     1 /* inode bitmap */ +
                                     sb->u.ext2_sb.s_itb_per_group /* inode table */;
-               overhead = sb->u.ext2_sb.s_es->s_first_data_block +
+               overhead = le32_to_cpu(sb->u.ext2_sb.s_es->s_first_data_block) +
                           sb->u.ext2_sb.s_groups_count * overhead_per_group;
        }
 
        tmp.f_type = EXT2_SUPER_MAGIC;
        tmp.f_bsize = sb->s_blocksize;
-       tmp.f_blocks = sb->u.ext2_sb.s_es->s_blocks_count - overhead;
+       tmp.f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead;
        tmp.f_bfree = ext2_count_free_blocks (sb);
-       tmp.f_bavail = tmp.f_bfree - sb->u.ext2_sb.s_es->s_r_blocks_count;
-       if (tmp.f_bfree < sb->u.ext2_sb.s_es->s_r_blocks_count)
+       tmp.f_bavail = tmp.f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count);
+       if (tmp.f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count))
                tmp.f_bavail = 0;
-       tmp.f_files = sb->u.ext2_sb.s_es->s_inodes_count;
+       tmp.f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
        tmp.f_ffree = ext2_count_free_inodes (sb);
        tmp.f_namelen = EXT2_NAME_LEN;
        copy_to_user(buf, &tmp, bufsiz);
index 500b7dc..a9e59ca 100644 (file)
  *  linux/fs/minix/truncate.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
 /*
@@ -140,7+143,7 @@ repeat:
                if (i < indirect_block)
                        goto repeat;
                ind = i + (u32 *) ind_bh->b_data;
-               tmp = *ind;
+               tmp = le32_to_cpu(*ind);
                if (!tmp)
                        continue;
                bh = get_hash_table (inode->i_dev, tmp,
@@ -149,12+152,12 @@ repeat:
                        brelse (bh);
                        goto repeat;
                }
-               if ((bh && bh->b_count != 1) || tmp != *ind) {
+               if ((bh && bh->b_count != 1) || tmp != le32_to_cpu(*ind)) {
                        retry = 1;
                        brelse (bh);
                        continue;
                }
-               *ind = 0;
+               *ind = cpu_to_le32(0);
                mark_buffer_dirty(ind_bh, 1);
                bforget(bh);
                if (free_count == 0) {
@@ -175,7+178,7 @@ repeat:
                ext2_free_blocks (inode, block_to_free, free_count);
        ind = (u32 *) ind_bh->b_data;
        for (i = 0; i < addr_per_block; i++)
-               if (*(ind++))
+               if (le32_to_cpu(*(ind++)))
                        break;
        if (i >= addr_per_block)
                if (ind_bh->b_count != 1)
@@ -195,6+198,93 @@ repeat:
        return retry;
 }
 
+static int trunc_indirect_swab32 (struct inode * inode, int offset, u32 * p)
+{
+       int i, tmp;
+       struct buffer_head * bh;
+       struct buffer_head * ind_bh;
+       u32 * ind;
+       unsigned long block_to_free = 0;
+       unsigned long free_count = 0;
+       int retry = 0;
+       int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+       int blocks = inode->i_sb->s_blocksize / 512;
+       int indirect_block = INDIRECT_BLOCK;
+
+       tmp = le32_to_cpu(*p);
+       if (!tmp)
+               return 0;
+       ind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
+       if (tmp != le32_to_cpu(*p)) {
+               brelse (ind_bh);
+               return 1;
+       }
+       if (!ind_bh) {
+               *p = cpu_to_le32(0);
+               return 0;
+       }
+repeat:
+       for (i = indirect_block ; i < addr_per_block ; i++) {
+               if (i < 0)
+                       i = 0;
+               if (i < indirect_block)
+                       goto repeat;
+               ind = i + (u32 *) ind_bh->b_data;
+               tmp = le32_to_cpu(*ind);
+               if (!tmp)
+                       continue;
+               bh = get_hash_table (inode->i_dev, tmp,
+                                    inode->i_sb->s_blocksize);
+               if (i < indirect_block) {
+                       brelse (bh);
+                       goto repeat;
+               }
+               if ((bh && bh->b_count != 1) || tmp != le32_to_cpu(*ind)) {
+                       retry = 1;
+                       brelse (bh);
+                       continue;
+               }
+               *ind = cpu_to_le32(0);
+               mark_buffer_dirty(ind_bh, 1);
+               bforget(bh);
+               if (free_count == 0) {
+                       block_to_free = tmp;
+                       free_count++;
+               } else if (free_count > 0 && block_to_free == tmp - free_count)
+                       free_count++;
+               else {
+                       ext2_free_blocks (inode, block_to_free, free_count);
+                       block_to_free = tmp;
+                       free_count = 1;
+               }
+/*             ext2_free_blocks (inode, tmp, 1); */
+               inode->i_blocks -= blocks;
+               inode->i_dirt = 1;
+       }
+       if (free_count > 0)
+               ext2_free_blocks (inode, block_to_free, free_count);
+       ind = (u32 *) ind_bh->b_data;
+       for (i = 0; i < addr_per_block; i++)
+               if (le32_to_cpu(*(ind++)))
+                       break;
+       if (i >= addr_per_block)
+               if (ind_bh->b_count != 1)
+                       retry = 1;
+               else {
+                       tmp = le32_to_cpu(*p);
+                       *p = cpu_to_le32(0);
+                       inode->i_blocks -= blocks;
+                       inode->i_dirt = 1;
+                       ext2_free_blocks (inode, tmp, 1);
+               }
+       if (IS_SYNC(inode) && buffer_dirty(ind_bh)) {
+               ll_rw_block (WRITE, 1, &ind_bh);
+               wait_on_buffer (ind_bh);
+       }
+       brelse (ind_bh);
+       return retry;
+}
+
 static int trunc_dindirect (struct inode * inode, int offset,
                            u32 * p)
 {
@@ -226,16+316,16 @@ repeat:
                if (i < dindirect_block)
                        goto repeat;
                dind = i + (u32 *) dind_bh->b_data;
-               tmp = *dind;
+               tmp = le32_to_cpu(*dind);
                if (!tmp)
                        continue;
-               retry |= trunc_indirect (inode, offset + (i * addr_per_block),
-                                         dind);
+               retry |= trunc_indirect_swab32 (inode, offset + (i * addr_per_block),
+                                               dind);
                mark_buffer_dirty(dind_bh, 1);
        }
        dind = (u32 *) dind_bh->b_data;
        for (i = 0; i < addr_per_block; i++)
-               if (*(dind++))
+               if (le32_to_cpu(*(dind++)))
                        break;
        if (i >= addr_per_block)
                if (dind_bh->b_count != 1)
@@ -255,6+345,65 @@ repeat:
        return retry;
 }
 
+static int trunc_dindirect_swab32 (struct inode * inode, int offset,
+                                  u32 * p)
+{
+       int i, tmp;
+       struct buffer_head * dind_bh;
+       u32 * dind;
+       int retry = 0;
+       int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+       int blocks = inode->i_sb->s_blocksize / 512;
+       int dindirect_block = DINDIRECT_BLOCK;
+
+       tmp = le32_to_cpu(*p);
+       if (!tmp)
+               return 0;
+       dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
+       if (tmp != le32_to_cpu(*p)) {
+               brelse (dind_bh);
+               return 1;
+       }
+       if (!dind_bh) {
+               *p = cpu_to_le32(0);
+               return 0;
+       }
+repeat:
+       for (i = dindirect_block ; i < addr_per_block ; i++) {
+               if (i < 0)
+                       i = 0;
+               if (i < dindirect_block)
+                       goto repeat;
+               dind = i + (u32 *) dind_bh->b_data;
+               tmp = le32_to_cpu(*dind);
+               if (!tmp)
+                       continue;
+               retry |= trunc_indirect_swab32 (inode, offset + (i * addr_per_block),
+                                               dind);
+               mark_buffer_dirty(dind_bh, 1);
+       }
+       dind = (u32 *) dind_bh->b_data;
+       for (i = 0; i < addr_per_block; i++)
+               if (le32_to_cpu(*(dind++)))
+                       break;
+       if (i >= addr_per_block)
+               if (dind_bh->b_count != 1)
+                       retry = 1;
+               else {
+                       tmp = le32_to_cpu(*p);
+                       *p = cpu_to_le32(0);
+                       inode->i_blocks -= blocks;
+                       inode->i_dirt = 1;
+                       ext2_free_blocks (inode, tmp, 1);
+               }
+       if (IS_SYNC(inode) && buffer_dirty(dind_bh)) {
+               ll_rw_block (WRITE, 1, &dind_bh);
+               wait_on_buffer (dind_bh);
+       }
+       brelse (dind_bh);
+       return retry;
+}
+
 static int trunc_tindirect (struct inode * inode)
 {
        int i, tmp;
@@ -287,14+436,14 @@ repeat:
                if (i < tindirect_block)
                        goto repeat;
                tind = i + (u32 *) tind_bh->b_data;
-               retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
-                       addr_per_block + (i + 1) * addr_per_block * addr_per_block,
-                       tind);
+               retry |= trunc_dindirect_swab32(inode, EXT2_NDIR_BLOCKS +
+                        addr_per_block + (i + 1) * addr_per_block * addr_per_block,
+                        tind);
                mark_buffer_dirty(tind_bh, 1);
        }
        tind = (u32 *) tind_bh->b_data;
        for (i = 0; i < addr_per_block; i++)
-               if (*(tind++))
+               if (le32_to_cpu(*(tind++)))
                        break;
        if (i >= addr_per_block)
                if (tind_bh->b_count != 1)
index 29e4bca..200a905 100644 (file)
@@ -160,4+160,14 @@ found_middle:
 #define find_first_zero_bit(addr, size) \
        find_next_zero_bit((addr), (size), 0)
 
+#ifdef __KERNEL__
+
+#define ext2_set_bit                 set_bit
+#define ext2_clear_bit               clear_bit
+#define ext2_test_bit                test_bit
+#define ext2_find_first_zero_bit     find_first_zero_bit
+#define ext2_find_next_zero_bit      find_next_zero_bit
+
+#endif /* __KERNEL__ */
+
 #endif /* _ALPHA_BITOPS_H */
index d9a4dc9..438ecb8 100644 (file)
 #undef htons
 
 #ifndef __LITTLE_ENDIAN
-#define __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
 #endif
 
 #ifndef __LITTLE_ENDIAN_BITFIELD
 #define __LITTLE_ENDIAN_BITFIELD
 #endif
 
+#ifdef __KERNEL__
+
+/*
+ * In-kernel byte order macros to handle stuff like
+ * byte-order-dependent filesystems etc.
+ */
+#define cpu_to_le32(x) (x)
+#define le32_to_cpu(x) (x)
+#define cpu_to_le16(x) (x)
+#define le16_to_cpu(x) (x)
+
+#define cpu_to_be32(x) htonl((x))
+#define be32_to_cpu(x) ntohl((x))
+#define cpu_to_be16(x) htons((x))
+#define be16_to_cpu(x) ntohs((x))
+
+#endif /* __KERNEL__ */
+
 extern unsigned long int       ntohl(unsigned long int);
 extern unsigned short int      ntohs(unsigned short int);
 extern unsigned long int       htonl(unsigned long int);
index 43caa22..6e639f4 100644 (file)
@@ -387,6+387,16 @@ extern long __strncpy_from_user(char *__to, const char *__from, long __to_len);
        __sfu_ret;                                                            \
 })
 
+/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
+extern long __strlen_user(const char *);
+
+extern inline long strlen_user(const char *str)
+{
+       long len = __strlen_user(str);
+       if (!access_ok(VERIFY_READ, str, len))
+               len = 0;
+       return len;
+}
 
 /*
  * About the exception table:
index e3ea8f5..d220f6f 100644 (file)
@@ -134,4+134,14 @@ extern __inline__ unsigned long ffz(unsigned long word)
        return word;
 }
 
+#ifdef __KERNEL__
+
+#define ext2_set_bit                 set_bit
+#define ext2_clear_bit               clear_bit
+#define ext2_test_bit                test_bit
+#define ext2_find_first_zero_bit     find_first_zero_bit
+#define ext2_find_next_zero_bit      find_next_zero_bit
+
+#endif /* __KERNEL__ */
+
 #endif /* _I386_BITOPS_H */
index 3f40767..7dff2a8 100644 (file)
 /* For avoiding bswap on i386 */
 #ifdef __KERNEL__
 #include <linux/config.h>
+
+/*
+ * In-kernel byte order macros to handle stuff like
+ * byte-order-dependent filesystems etc.
+ */
+#define cpu_to_le32(x) (x)
+#define le32_to_cpu(x) (x)
+#define cpu_to_le16(x) (x)
+#define le16_to_cpu(x) (x)
+
+#define cpu_to_be32(x) htonl((x))
+#define be32_to_cpu(x) ntohl((x))
+#define cpu_to_be16(x) htons((x))
+#define be16_to_cpu(x) ntohs((x))
+
 #endif
 
 extern unsigned long int       ntohl(unsigned long int);
index d6b42b7..93f6fd2 100644 (file)
@@ -407,5+407,33 @@ strncpy_from_user(char *dst, const char *src, long count)
        return res;
 }
 
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+extern inline long strlen_user(const char * s)
+{
+       long res;
+       __asm__ __volatile__(
+               "\n"
+               "0:\trepne ; scasb\n\t"
+               "notl %0\n"
+               "1:\n"
+               ".section .fixup,\"ax\"\n"
+               "2:\txorl %0,%0\n\t"
+               "jmp 1b\n"
+               ".section __ex_table,\"a\"\n\t"
+               ".align 4\n\t"
+               ".long 0b,2b\n"
+               ".text"
+               :"=c" (res)
+               :"D" (s),"a" (0),"0" (0xffffffff)
+               :"di");
+       if (!access_ok(VERIFY_READ, s, res))
+               res = 0;
+       return res;
+}
+
 
 #endif /* __i386_UACCESS_H */
index b99eaa7..2283c27 100644 (file)
@@ -122,6+122,7 @@ extern int max_files, nr_files;
 #ifdef __KERNEL__
 
 #include <asm/semaphore.h>
+#include <asm/byteorder.h>
 #include <asm/bitops.h>
 
 extern void buffer_init(void);
@@ -665,6+666,7 @@ extern long generic_file_read(struct inode *, struct file *, char *, unsigned lo
 
 extern void put_super(kdev_t dev);
 unsigned long generate_cluster(kdev_t dev, int b[], int size);
+unsigned long generate_cluster_swab32(kdev_t dev, int b[], int size);
 extern kdev_t ROOT_DEV;
 
 extern void show_buffers(void);
index 198260a..6174845 100644 (file)
@@ -118,6+118,7 @@ struct sockaddr_in {
 #define INADDR_ALLHOSTS_GROUP  0xe0000001      /* 224.0.0.1   */
 #define INADDR_MAX_LOCAL_GROUP  0xe00000ff      /* 224.0.0.255 */
 
+
 /* <asm/byteorder.h> contains the htonl type stuff.. */
 #include <asm/byteorder.h> 
 
index 2d4e769..e8ddfb0 100644 (file)
@@ -465,8+465,8 @@ extern __inline__ void skb_trim(struct sk_buff *skb, int len)
 
 extern struct sk_buff *                skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
 extern int                     datagram_select(struct sock *sk, int sel_type, select_table *wait);
-extern void                    skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
-extern void                    skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size);
+extern int                     skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
+extern int                     skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size);
 extern void                    skb_free_datagram(struct sock * sk, struct sk_buff *skb);
 
 #endif /* __KERNEL__ */
index ed2b77c..d862f8f 100644 (file)
@@ -175,8+175,8 @@ extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr,
 #define SOPRI_BACKGROUND       2
 
 #ifdef __KERNEL__
-extern void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
-extern void memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, 
+extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, 
                                int offset, int len);
 extern unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata, 
                                                   struct iovec *iov, 
@@ -184,7+184,7 @@ extern unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata,
                                                   int len, int csum);
 
 extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
-extern void memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
 extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
 extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
 #endif
index c7bd998..f7bb04c 100644 (file)
@@ -106,11+106,11 @@ extern void               ip_queue_xmit(struct sock *sk,
                                      int free);
 extern void            ip_init(void);
 extern int             ip_build_xmit(struct sock *sk,
-                                     void getfrag (const void *,
-                                                   __u32,
-                                                   char *,
-                                                   unsigned int,
-                                                   unsigned int),
+                                     int getfrag (const void *,
+                                                  __u32,
+                                                  char *,
+                                                  unsigned int,
+                                                  unsigned int),
                                      const void *frag,
                                      unsigned short int length,
                                      __u32 daddr,
index b42c3f0..5b10429 100644 (file)
@@ -133,7+133,7 @@ extern int                  ipv6_reassembly(struct sk_buff **skb,
  *     Function prototype for build_xmit
  */
 
-typedef void           (*inet_getfrag_t) (const void *data,
+typedef int            (*inet_getfrag_t) (const void *data,
                                           struct in6_addr *addr,
                                           char *,
                                           unsigned int, unsigned int);
index 21c3e65..8c1bf9e 100644 (file)
@@ -382,7+382,7 @@ static __inline__ unsigned short tcp_raise_window(struct sock *sk)
          * old_window - received_bytes_on_that_win
         */
 
-       cur_win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
+       cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd);
 
 
        /*
@@ -396,82+396,7 @@ static __inline__ unsigned short tcp_raise_window(struct sock *sk)
        return res;
 }
 
-/*
- *      This function returns the amount that we can raise the
- *      usable window based on the following constraints
- *  
- *     1. The window can never be shrunk once it is offered (RFC 793)
- *     2. We limit memory per socket
- */
-
-
-static __inline__ unsigned short tcp_select_window(struct sock *sk)
-{
-       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
-       long free_space = sock_rspace(sk);
-       long window;
-       long cur_win;
-       long usable;
-       
-       if (sk->window_clamp)
-               free_space = min(sk->window_clamp, free_space);
-       
-       /*
-        * compute the actual window i.e.
-        * old_window - received_bytes_on_that_win
-        */
-
-       cur_win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
-       window  = tp->rcv_wnd;
-       
-       if ( cur_win < 0 )
-       {
-               cur_win = 0;
-               printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n",
-                      tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup);
-       }
-
-       /*
-        * RFC 1122:
-        * "the suggested [SWS] avoidance algoritm for the receiver is to keep
-        *  RECV.NEXT + RCV.WIN fixed until:
-        *  RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
-        *
-        * i.e. don't raise the right edge of the window until you can't raise
-        * it MSS bytes
-        */
-
-       /*
-        * It would be a good idea if it didn't break header prediction.
-        * and BSD made the header predition standard...
-        * It expects the same value in the header i.e. th->window to be
-        * constant
-        */
-
-       if (tp->rcv_wnd >= free_space)
-       {
-               if (cur_win > (sk->mss << 1))
-                       goto out;
-       }
-
-       usable = free_space - cur_win;
-
-#define WROUND(X, Y) ((X + (Y-1)) & (Y-1))
-               
-       window += WROUND(min(usable, sk->mss), 1024);
-
-#undef WROUND
-
-       if (window < cur_win)
-       {
-               window = cur_win;
-       }
-
-  out: 
-       tp->rcv_wnd = window;
-       tp->rcv_wup = tp->rcv_nxt;
-       return window;
-}
+extern unsigned short  tcp_select_window(struct sock *sk);
 
 /*
  * List all states of a TCP socket that can be viewed as a "connected"
index 9dc8384..aef113c 100644 (file)
@@ -736,16+736,15 @@ int atif_ioctl(int cmd, void *arg)
        struct device *dev;
        struct atalk_iface *atif;
        int ro=(cmd==SIOCSIFADDR);
-       int err=verify_area(ro?VERIFY_READ:VERIFY_WRITE, arg,sizeof(atreq));
+       int err;
        int ct;
        int limit;
        struct rtentry rtdef;
        
-       if(err)
-               return err;
-       
-       copy_from_user(&atreq,arg,sizeof(atreq));
-       
+       err = copy_from_user(&atreq,arg,sizeof(atreq));
+       if (err)
+               return -EFAULT; 
+
        if((dev=dev_get(atreq.ifr_name))==NULL)
                return -ENODEV;
                
@@ -855,8+854,13 @@ int atif_ioctl(int cmd, void *arg)
                        ((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_node=ATADDR_BCAST;
                        break;
        }
-       copy_to_user(arg,&atreq,sizeof(atreq));
-       return 0;
+       err = copy_to_user(arg,&atreq,sizeof(atreq));
+
+       if (err)
+       {
+               err = -EFAULT;
+       }
+       return err;
 }
 
 /*
@@ -868,11+872,10 @@ static int atrtr_ioctl(unsigned int cmd, void *arg)
        int err;
        struct rtentry rt;
        
-       err=verify_area(VERIFY_READ, arg, sizeof(rt));
-       if(err)
-               return err;
-       copy_from_user(&rt,arg,sizeof(rt));
-       
+       err = copy_from_user(&rt,arg,sizeof(rt));
+       if (err)
+               return -EFAULT; 
+
        switch(cmd)
        {
                case SIOCDELRT:
@@ -1077,15+1080,10 @@ static int atalk_getsockopt(struct socket *sock, int level, int optname,
                default:
                        return -EOPNOTSUPP;
        }
-       err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
-       if(err)
-               return err;
-       put_user(sizeof(int),optlen);
-       err=verify_area(VERIFY_WRITE,optval,sizeof(int));
-       if (err) 
-               return err;
-       put_user(val, (int *)optval);
-       return(0);
+       err = put_user(sizeof(int),optlen);
+       if (!err)
+               err = put_user(val, (int *) optval);
+       return err;
 }
 
 /*
@@ -1736,8+1734,13 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int n
        if(sk->debug)
                printk("SK %p: Copy user data (%d bytes).\n", sk, len);
                
-       memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len);
-
+       err = memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len);
+       if (err)
+       {
+               kfree_skb(skb, FREE_WRITE);
+               return err;
+       }
+               
        if(sk->no_check==1)
                ddp->deh_sum=0;
        else
@@ -1816,7+1819,7 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int
        struct ddpehdr  *ddp = NULL;
        int copied = 0;
        struct sk_buff *skb;
-       int er;
+       int er = 0;
        
        if(sk->err)
                return sock_error(sk);
@@ -1834,14+1837,18 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int
                copied=ddp->deh_len;
                if(copied > size)
                        copied=size;
-               skb_copy_datagram_iovec(skb,0,msg->msg_iov,copied);
+               er = skb_copy_datagram_iovec(skb,0,msg->msg_iov,copied);
+               if (er)
+                       goto out;
        }
        else
        {
                copied=ddp->deh_len - sizeof(*ddp);
                if (copied > size)
                        copied = size;
-               skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
+               er = skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
+               if (er) 
+                       goto out; 
        }
        if(sat)
        {
@@ -1850,8+1857,9 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int
                sat->sat_addr.s_node=ddp->deh_snode;
                sat->sat_addr.s_net=ddp->deh_snet;
        }
+out:
        skb_free_datagram(sk, skb);
-       return(copied);
+       return er ? er : (copied);
 }              
 
 
@@ -1900,11+1908,7 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
                        {
                                if(sk->stamp.tv_sec==0)
                                        return -ENOENT;
-                               err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
-                               if(err)
-                                       return err;
-                                       copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
-                               return 0;
+                               return copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
                        }
                        return -EINVAL;
                /*
@@ -1950,11+1954,7 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
                default:
                        return -EINVAL;
        }
-       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
-       if(err)
-               return err;
-       put_user(amount, (int *)arg);
-       return(0);
+       return put_user(amount, (int *)arg);
 }
 
 static struct proto_ops atalk_proto_ops = {
index 95edf89..c1fd043 100644 (file)
@@ -1442,22+1442,20 @@ int br_ioctl(unsigned int cmd, void *arg)
        switch(cmd)
        {
                case SIOCGIFBR: /* get bridging control blocks */
-                       err = verify_area(VERIFY_WRITE, arg, 
-                               sizeof(struct br_stat));
-                       if(err)
-                               return err;
                        memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
                        memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*No_of_ports);
-                       copy_to_user(arg, &br_stats, sizeof(struct br_stat));
-                       return(0);
+                       err = copy_to_user(arg, &br_stats, sizeof(struct br_stat));
+                       if (err)
+                       {
+                               err = -EFAULT;
+                       }
+                       return err;
                case SIOCSIFBR:
                        if (!suser())
                                return -EPERM;
-                       err = verify_area(VERIFY_READ, arg, 
-                               sizeof(struct br_cf));
-                       if(err)
-                               return err;
-                       copy_from_user(&bcf, arg, sizeof(struct br_cf));
+                       err = copy_from_user(&bcf, arg, sizeof(struct br_cf));
+                       if (err)
+                               return -EFAULT; 
                        switch (bcf.cmd) {
                                case BRCMD_BRIDGE_ENABLE:
                                        if (br_stats.flags & BR_UP)
index 830551e..8480beb 100644 (file)
@@ -166,9+166,15 @@ void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
  *     Copy a datagram to a linear buffer.
  */
 
-void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
+int skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
 {
-       copy_to_user(to,skb->h.raw+offset,size);
+       int err;
+       err = copy_to_user(to, skb->h.raw+offset, size);
+       if (err)
+       {
+               err = -EFAULT;
+       }
+       return err;
 }
 
 
@@ -176,9+182,16 @@ void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
  *     Copy a datagram to an iovec.
  */
  
-void skb_copy_datagram_iovec(struct sk_buff *skb, int offset, struct iovec *to, int size)
+int skb_copy_datagram_iovec(struct sk_buff *skb, int offset, struct iovec *to,
+                           int size)
 {
-       memcpy_toiovec(to,skb->h.raw+offset,size);
+       int err;
+       err = memcpy_toiovec(to, skb->h.raw+offset, size);
+       if (err)
+       {
+               err = -EFAULT;
+       }
+       return err;
 }
 
 /*
index d3d235c..5cfa093 100644 (file)
@@ -793,11+793,10 @@ static int dev_ifconf(char *arg)
        /*
         *      Fetch the caller's info block. 
         */
-        
-       err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));
-       if(err)
-               return err;
-       copy_from_user(&ifc, arg, sizeof(struct ifconf));
+       
+       err = copy_from_user(&ifc, arg, sizeof(struct ifconf));
+       if (err)
+               return -EFAULT; 
        len = ifc.ifc_len;
        pos = ifc.ifc_buf;
 
@@ -805,11+804,7 @@ static int dev_ifconf(char *arg)
         *      We now walk the device list filling each active device
         *      into the array.
         */
-        
-       err=verify_area(VERIFY_WRITE,pos,len);
-       if(err)
-               return err;
-       
+       
        /*
         *      Loop over the interfaces, and write an info block for each. 
         */
@@ -835,7+830,9 @@ static int dev_ifconf(char *arg)
                 *      Write this block to the caller's space. 
                 */
                 
-               copy_to_user(pos, &ifr, sizeof(struct ifreq));
+               err = copy_to_user(pos, &ifr, sizeof(struct ifreq));
+               if (err)
+                       return -EFAULT; 
                pos += sizeof(struct ifreq);
                len -= sizeof(struct ifreq);            
        }
@@ -846,8+843,10 @@ static int dev_ifconf(char *arg)
         
        ifc.ifc_len = (pos - ifc.ifc_buf);
        ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;
-       copy_to_user(arg, &ifc, sizeof(struct ifconf));
-       
+       err = copy_to_user(arg, &ifc, sizeof(struct ifconf));
+       if (err)
+               return -EFAULT; 
+
        /*
         *      Report how much was filled in
         */
@@ -956,17+955,15 @@ static int dev_ifsioc(void *arg, unsigned int getset)
 {
        struct ifreq ifr;
        struct device *dev;
-       int ret;
+       int ret, err;
 
        /*
         *      Fetch the caller's info block into kernel space
         */
-
-       int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq));
-       if(err)
-               return err;
        
-       copy_from_user(&ifr, arg, sizeof(struct ifreq));
+       err = copy_from_user(&ifr, arg, sizeof(struct ifreq));
+       if (err)
+               return -EFAULT; 
 
        /*
         *      See which interface the caller is talking about. 
@@ -1266,8+1263,13 @@ static int dev_ifsioc(void *arg, unsigned int getset)
                           (getset <= (SIOCDEVPRIVATE + 15))) {
                                if(dev->do_ioctl==NULL)
                                        return -EOPNOTSUPP;
-                               ret=dev->do_ioctl(dev, &ifr, getset);
-                               copy_to_user(arg,&ifr,sizeof(struct ifreq));
+                               ret = dev->do_ioctl(dev, &ifr, getset);
+                               if (!ret)
+                               {
+                                       err = copy_to_user(arg,&ifr,sizeof(struct ifreq));
+                                       if (err)
+                                               ret = -EFAULT;
+                               }
                                break;
                        }
                        
@@ -1278,8+1280,10 @@ static int dev_ifsioc(void *arg, unsigned int getset)
  *     The load of calls that return an ifreq and ok (saves memory).
  */
 rarok:
-       copy_to_user(arg, &ifr, sizeof(struct ifreq));
-       return 0;
+       err = copy_to_user(arg, &ifr, sizeof(struct ifreq));
+       if (err)
+               err = -EFAULT;
+       return err;
 }
 
 
index 77bd717..b18e062 100644 (file)
  *             Andrew Lunn     :       Errors in iovec copying.
  *             Pedro Roque     :       Added memcpy_fromiovecend and
  *                                     csum_..._fromiovecend.
+ *      Andi Kleen  :   fixed error handling for 2.1
  */
 
 
@@ -29,6+30,12 @@ extern inline int min(int x, int y)
        return x>y?y:x;
 }
 
+
+/*
+ *     Verify iovec
+ *     verify area does a simple check for completly bogus addresses
+ */
+
 int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
 {
        int err=0;
@@ -37,14+44,20 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
        
        if(m->msg_name!=NULL)
        {
-               if(mode==VERIFY_READ) {
+               if(mode==VERIFY_READ)
+               {
                        err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
-               } else
+               }
+               else
+               {
                        err=verify_area(mode, m->msg_name, m->msg_namelen);
+               }
+               
                if(err<0)
                        return err;
                m->msg_name = address;
        }
+       
        if(m->msg_control!=NULL)
        {
                err=verify_area(mode, m->msg_control, m->msg_controllen);
@@ -54,11+67,12 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
        
        for(ct=0;ct<m->msg_iovlen;ct++)
        {
-               err=verify_area(VERIFY_READ, &m->msg_iov[ct], sizeof(struct iovec));
-               if(err)
+               err = copy_from_user(&iov[ct], &m->msg_iov[ct],
+                                    sizeof(struct iovec));
+               if (err)
                        return err;
-               copy_from_user(&iov[ct], &m->msg_iov[ct], sizeof(struct iovec));
-               err=verify_area(mode, iov[ct].iov_base, iov[ct].iov_len);
+               
+               err = verify_area(mode, iov[ct].iov_base, iov[ct].iov_len);
                if(err)
                        return err;
                len+=iov[ct].iov_len;
@@ -71,14+85,18 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
  *     Copy kernel to iovec.
  */
  
-void memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
+int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
 {
+       int err; 
        while(len>0)
        {
                if(iov->iov_len)
                {
                        int copy = min(iov->iov_len,len);
-                       copy_to_user(iov->iov_base,kdata,copy);
+                       err = copy_to_user(iov->iov_base,kdata,copy);
+                       if (err) {
+                               return err; 
+                       }
                        kdata+=copy;
                        len-=copy;
                        iov->iov_len-=copy;
@@ -86,20+104,26 @@ void memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
                }
                iov++;
        }
+       return 0; 
 }
 
 /*
  *     Copy iovec to kernel.
  */
  
-void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
+int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
 {
+       int err; 
        while(len>0)
        {
                if(iov->iov_len)
                {
                        int copy=min(len,iov->iov_len);
-                       copy_from_user(kdata, iov->iov_base, copy);
+                       err = copy_from_user(kdata, iov->iov_base, copy);
+                       if (err)
+                       {
+                               return err; 
+                       }
                        len-=copy;
                        kdata+=copy;
                        iov->iov_base+=copy;
@@ -107,6+131,7 @@ void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
                }
                iov++;
        }
+       return 0; 
 }
 
 
@@ -114,9+139,10 @@ void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
  *     For use with ip_build_xmit
  */
 
-void memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, 
-                        int len)
+int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
+                       int len)
 {
+       int err; 
        while(offset>0)
        {
                if (offset > iov->iov_len)
@@ -133,21+159,30 @@ void memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
                        copy = min(len, iov->iov_len - offset);
                        offset = 0;
 
-                       copy_from_user(kdata, base, copy);
+                       err = copy_from_user(kdata, base, copy);
+                       if (err)
+                       {
+                               return err;
+                       }
                        len-=copy;
                        kdata+=copy;
                }
-               iov++;  
+               iov++;
        }
 
        while (len>0)
        {
                int copy=min(len, iov->iov_len);
-               copy_from_user(kdata, iov->iov_base, copy);
+               err = copy_from_user(kdata, iov->iov_base, copy);
+               if (err)
+               {
+                       return err;
+               }
                len-=copy;
                kdata+=copy;
                iov++;
        }
+       return 0;
 }
 
 /*
@@ -157,6+192,9 @@ void memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
  *
  *     ip_build_xmit must ensure that when fragmenting only the last
  *     call to this function will be unaligned also.
+ *
+ *     FIXME: add an error handling path when a copy/checksum from
+ *     user space failed because of a invalid pointer.
  */
 
 unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata, 
@@ -190,13+228,18 @@ unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata,
                                               partial_cnt);
                        }
 
+                       /*      
+                        *      FIXME: add exception handling to the
+                        *      csum functions and set *err when an
+                        *      exception occurs.
+                        */
                        csum = csum_partial_copy_fromuser(base, kdata, 
                                                          copy, csum);
 
                        len   -= copy + partial_cnt;
                        kdata += copy + partial_cnt;
                }
-               iov++;                  
+               iov++;  
        }
 
        while (len>0)
@@ -226,8+269,7 @@ unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata,
                        }
                }
 
-               csum = csum_partial_copy_fromuser(base, kdata, 
-                                                 copy, csum);
+               csum = csum_partial_copy_fromuser(base, kdata, copy, csum);
                len   -= copy + partial_cnt;
                kdata += copy + partial_cnt;
                iov++;
index 7773016..e041c11 100644 (file)
@@ -634,7+634,7 @@ void kfree_skb(struct sk_buff *skb, int rw)
 struct sk_buff *alloc_skb(unsigned int size,int priority)
 {
        struct sk_buff *skb;
-       int len=size;
+       int len;
        unsigned char *bptr;
 
        if (intr_count && priority!=GFP_ATOMIC) 
@@ -648,6+648,8 @@ struct sk_buff *alloc_skb(unsigned int size,int priority)
        }
 
        size=(size+15)&~15;             /* Allow for alignments. Make a multiple of 16 bytes */
+       len = size;
+       
        size+=sizeof(struct sk_buff);   /* And stick the control itself on the end */
        
        /*
@@ -748,7+750,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
        int inbuff = 0;
        
        IS_SKB(skb);
-       if (skb_tailroom(skb) >= sizeof(struct sk_buff))
+       if (!skb->inclone && skb_tailroom(skb) >= sizeof(struct sk_buff))
        {
                n = ((struct sk_buff *) skb->end) - 1;
                skb->end -= sizeof(struct sk_buff);
index b5fcaa0..0654192 100644 (file)
  */
 
 int sock_setsockopt(struct sock *sk, int level, int optname,
-               char *optval, int optlen)
+                   char *optval, int optlen)
 {
        int val;
        int valbool;
        int err;
        struct linger ling;
+       int ret = 0;
 
        /*
         *      Options without arguments
@@ -144,33+145,36 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
                
        if (optval == NULL) 
                return(-EINVAL);
-
-       err=verify_area(VERIFY_READ, optval, sizeof(int));
-       if(err)
-               return err;
        
-       get_user(val, (int *)optval);
+       err = get_user(val, (int *)optval);
+       if (err)
+               return err;
+       
        valbool = val?1:0;
        
        switch(optname) 
        {
                case SO_DEBUG:  
                        if(val && !suser())
-                               return(-EPERM);
-                       sk->debug=valbool;
-                       return 0;
+                       {
+                               ret = -EPERM;
+                       }
+                       else
+                               sk->debug=valbool;
+                       break;
                case SO_REUSEADDR:
                        sk->reuse = valbool;
-                       return(0);
+                       break;
                case SO_TYPE:
                case SO_ERROR:
-                       return(-ENOPROTOOPT);
+                       ret = -ENOPROTOOPT;
+                       break;
                case SO_DONTROUTE:
                        sk->localroute=valbool;
-                       return 0;
+                       break;
                case SO_BROADCAST:
                        sk->broadcast=valbool;
-                       return 0;
+                       break;
                case SO_SNDBUF:
                        if(val > SK_WMEM_MAX*2)
                                val = SK_WMEM_MAX*2;
@@ -179,7+183,7 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
                        if(val > 65535)
                                val = 65535;
                        sk->sndbuf = val;
-                       return 0;
+                       break;
 
                case SO_RCVBUF:
                        if(val > SK_RMEM_MAX*2)
@@ -189,41+193,45 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
                        if(val > 65535)
                                val = 65535;
                        sk->rcvbuf = val;
-                       return(0);
+                       break;
 
                case SO_KEEPALIVE:
+#ifdef CONFIG_INET
                        if (sk->protocol == IPPROTO_TCP)
                        {
                                tcp_set_keepalive(sk, valbool);
                        }
+#endif
                        sk->keepopen = valbool;
-                       return(0);
+                       break;
 
                case SO_OOBINLINE:
                        sk->urginline = valbool;
-                       return(0);
+                       break;
 
                case SO_NO_CHECK:
                        sk->no_check = valbool;
-                       return(0);
+                       break;
 
                case SO_PRIORITY:
                        if (val >= 0 && val < DEV_NUMBUFFS) 
                        {
                                sk->priority = val;
                        } 
-                       else 
+                       else
                        {
                                return(-EINVAL);
                        }
-                       return(0);
+                       break;
 
 
                case SO_LINGER:
-                       err=verify_area(VERIFY_READ,optval,sizeof(ling));
-                       if(err)
-                               return err;
-                       copy_from_user(&ling,optval,sizeof(ling));
+                       err = copy_from_user(&ling,optval,sizeof(ling));
+                       if (err)
+                       {
+                               ret = -EFAULT;
+                               break;
+                       }
                        if(ling.l_onoff==0)
                                sk->linger=0;
                        else
@@ -231,15+239,16 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
                                sk->lingertime=ling.l_linger;
                                sk->linger=1;
                        }
-                       return 0;
+                       break;
 
                case SO_BSDCOMPAT:
                        sk->bsdism = valbool;
-                       return 0;
+                       break;
                        
                default:
                        return(-ENOPROTOOPT);
        }
+       return ret;
 }
 
 
@@ -303,17+312,13 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
                        break;
                
                case SO_LINGER: 
-                       err=verify_area(VERIFY_WRITE,optval,sizeof(ling));
-                       if(err)
-                               return err;
-                       err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
-                       if(err)
-                               return err;
-                       put_user(sizeof(ling), optlen);
-                       ling.l_onoff=sk->linger;
-                       ling.l_linger=sk->lingertime;
-                       copy_to_user(optval,&ling,sizeof(ling));
-                       return 0;
+                       err = put_user(sizeof(ling), optlen);
+                       if (!err) {
+                               ling.l_onoff=sk->linger;
+                               ling.l_linger=sk->lingertime;
+                               err = copy_to_user(optval,&ling,sizeof(ling));
+                       }
+                       return err;
                
                case SO_BSDCOMPAT:
                        val = sk->bsdism;
@@ -322,17+327,11 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
                default:
                        return(-ENOPROTOOPT);
        }
-       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-       if(err)
-               return err;
-       put_user(sizeof(int), optlen);
-
-       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
-       if(err)
-               return err;
-       put_user(val,(unsigned int *)optval);
+       err = put_user(sizeof(int), optlen);
+       if (!err)
+               err = put_user(val,(unsigned int *)optval);
 
-       return(0);
+       return err;
 }
 
 struct sock *sk_alloc(int priority)
index 89f1960..092eaad 100644 (file)
@@ -1208,10+1208,9 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        {
                case FIOSETOWN:
                case SIOCSPGRP:
-                       err=verify_area(VERIFY_READ,(int *)arg,sizeof(long));
-                       if(err)
-                               return err;
-                       get_user(pid, (int *) arg);
+                       err = get_user(pid, (int *) arg);
+                       if (err)
+                               return err; 
                        /* see inet_fcntl */
                        if (current->pid != pid && current->pgrp != -pid && !suser())
                                return -EPERM;
@@ -1219,19+1218,16 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        return(0);
                case FIOGETOWN:
                case SIOCGPGRP:
-                       err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(int));
-                       if(err)
-                               return err;
-                       put_user(sk->proc, (int *)arg);
-                       return(0);                      
+                       return put_user(sk->proc, (int *)arg);
                case SIOCGSTAMP:
                        if(sk->stamp.tv_sec==0)
                                return -ENOENT;
-                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
-                       if(err)
-                               return err;
-                       copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
-                       return 0;
+                       err = copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
+                       if (err)
+                       {
+                               err = -EFAULT;
+                       }
+                       return err;
                case SIOCADDRT:
                case SIOCDELRT:
                        return(ip_rt_ioctl(cmd,(void *) arg));
index e4b9f15..090808b 100644 (file)
@@ -2179,20+2179,18 @@ int arp_ioctl(unsigned int cmd, void *arg)
                        if (!suser())
                                return -EPERM;
                case SIOCGARP:
-                       err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
+                       err = copy_from_user(&r, arg, sizeof(struct arpreq));
                        if (err)
-                               return err;
-                       copy_from_user(&r, arg, sizeof(struct arpreq));
+                               return -EFAULT; 
                        break;
                case OLD_SIOCDARP:
                case OLD_SIOCSARP:
                        if (!suser())
                                return -EPERM;
                case OLD_SIOCGARP:
-                       err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq_old));
+                       err = copy_from_user(&r, arg, sizeof(struct arpreq_old));
                        if (err)
-                               return err;
-                       copy_from_user(&r, arg, sizeof(struct arpreq_old));
+                               return -EFAULT; 
                        memset(&r.arp_dev, 0, sizeof(r.arp_dev));
                        break;
                default:
@@ -2250,17+2248,15 @@ int arp_ioctl(unsigned int cmd, void *arg)
                        }
                        return err;
                case SIOCGARP:
-                       err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
-                       if (err)
-                               return err;
                        err = arp_req_get(&r, dev);
                        if (!err)
-                               copy_to_user(arg, &r, sizeof(r));
+                       {
+                               err = copy_to_user(arg, &r, sizeof(r));
+                               if (err)
+                                       err = -EFAULT;
+                       }
                        return err;
                case OLD_SIOCGARP:
-                       err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq_old));
-                       if (err)
-                               return err;
                        r.arp_flags &= ~ATF_PUBL;
                        err = arp_req_get(&r, dev);
                        if (err < 0)
@@ -2269,7+2265,11 @@ int arp_ioctl(unsigned int cmd, void *arg)
                                err = arp_req_get(&r, dev);
                        }
                        if (!err)
-                               copy_to_user(arg, &r, sizeof(struct arpreq_old));
+                       {
+                               err = copy_to_user(arg, &r, sizeof(struct arpreq_old));
+                               if (err)
+                                       err = -EFAULT;
+                       }
                        return err;
        }
        /*NOTREACHED*/
index 374ef8d..173704f 100644 (file)
@@ -474,16+474,17 @@ static void icmp_out_count(int type)
  *     Checksum each fragment, and on the first include the headers and final checksum.
  */
  
-static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
+static int icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
 {
        struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
        struct icmphdr *icmph;
        unsigned long csum;
 
-       if (offset) {
+       if (offset)
+       {
                icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr), 
                                to, fraglen,icmp_param->csum);
-               return;
+               return 0;
        }
 
        /*
@@ -499,6+500,8 @@ static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int of
                fraglen-sizeof(struct icmphdr), csum);
        icmph=(struct icmphdr *)to;
        icmph->checksum = csum_fold(csum);
+
+       return 0; 
 }
  
 /*
index 77880db..8f87877 100644 (file)
@@ -504,11+504,11 @@ fragment:
  */
 
 int ip_build_xmit(struct sock *sk,
-                  void getfrag (const void *,
-                                __u32,
-                                char *,
-                                unsigned int,  
-                                unsigned int),
+                 int getfrag (const void *,
+                              __u32,
+                              char *,
+                              unsigned int,    
+                              unsigned int),
                   const void *frag,
                   unsigned short int length,
                   __u32 daddr,
@@ -529,6+529,7 @@ int ip_build_xmit(struct sock *sk,
        struct hh_cache * hh=NULL;
        int nfrags=0;
        __u32 true_daddr = daddr;
+       int err; 
 
        if (opt && opt->srr && !sk->ip_hdrincl)
          daddr = opt->faddr;
@@ -648,18+649,31 @@ int ip_build_xmit(struct sock *sk,
                        }
                        iph->check=0;
                        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-                       getfrag(frag,saddr,((char *)iph)+iph->ihl*4,0, length-iph->ihl*4);
+                       err = getfrag(frag,saddr,((char *)iph)+iph->ihl*4,0, length-iph->ihl*4);
                }
                else
-                       getfrag(frag,saddr,(void *)iph,0,length);
+                       err = getfrag(frag, saddr, (void *)iph, 0, length);
+               
                dev_unlock_list();
+               
+               if (err)
+               {
+                       err = -EFAULT;
+               }
+
 #ifdef CONFIG_FIREWALL
-               if(call_out_firewall(PF_INET, skb->dev, iph, NULL)< FW_ACCEPT)
+               if(!err && call_out_firewall(PF_INET, skb->dev, iph, NULL)< FW_ACCEPT)
                {
-                       kfree_skb(skb, FREE_WRITE);
-                       return -EPERM;
+                       err = -EPERM; 
                }
 #endif
+
+               if (err)
+               {
+                       kfree_skb(skb, FREE_WRITE);
+                       return err;
+               }
+
 #ifdef CONFIG_IP_ACCT
                ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
 #endif         
@@ -675,7+689,7 @@ int ip_build_xmit(struct sock *sk,
        if (!sk->ip_hdrincl)
                length -= sizeof(struct iphdr);
                
-       if(opt) 
+       if(opt)
        {
                length -= opt->optlen;
                fragheaderlen = dev->hard_header_len + sizeof(struct iphdr) + opt->optlen;
@@ -688,8+702,8 @@ int ip_build_xmit(struct sock *sk,
                        fragheaderlen += 20;
                
                /*
-                *      Fragheaderlen is the size of 'overhead' on each buffer. Now work
-                *      out the size of the frames to send.
+                *      Fragheaderlen is the size of 'overhead' on each buffer.
+                *      Now work out the size of the frames to send.
                 */
         
                maxfraglen = ((dev->mtu-20) & ~7) + fragheaderlen;
@@ -758,7+772,7 @@ int ip_build_xmit(struct sock *sk,
                {
                        ip_statistics.IpOutDiscards++;
                        if(nfrags>1)
-                               ip_statistics.IpFragCreates++;                  
+                               ip_statistics.IpFragCreates++;
                        dev_unlock_list();
                        return(error);
                }
@@ -795,7+809,7 @@ int ip_build_xmit(struct sock *sk,
                                skb->arp = 0;
 #if RT_CACHE_DEBUG >= 2
                                printk("ip_build_xmit: hh miss %08x via %08x\n", rt->rt_dst, rt->rt_gateway);
-#endif                         
+#endif
                        }
                }
                else if (dev->hard_header)
@@ -856,20+870,29 @@ int ip_build_xmit(struct sock *sk,
                 *      User data callback
                 */
 
-               getfrag(frag, saddr, data, offset, fraglen-fragheaderlen);
+               err = getfrag(frag, saddr, data, offset, fraglen-fragheaderlen);
+               if (err)
+               {
+                       err = -EFAULT;
+               }
                
                /*
                 *      Account for the fragment.
                 */
                 
 #ifdef CONFIG_FIREWALL
-               if(!offset && call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+               if(!err && !offset && call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+               {
+                       err = -EPERM; 
+               }
+#endif
+               if (err)
                {
                        kfree_skb(skb, FREE_WRITE);
                        dev_unlock_list();
-                       return -EPERM;
+                       return err;
                }
-#endif         
+
 #ifdef CONFIG_IP_ACCT
                if(!offset)
                        ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_OUT);
index e196948..89092de 100644 (file)
@@ -123,11+123,11 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
        }
        else
        {
-               err=verify_area(VERIFY_READ, optval, sizeof(int));
-               if(err)
-                       return err;
-               get_user(val, (int *) optval);
-               get_user(ucval, (unsigned char *) optval);
+               err = get_user(val, (int *) optval);
+               if (!err)
+                       err = get_user(ucval, (unsigned char *) optval);
+               if (err)
+                       return err; 
        }
        
        if(level!=SOL_IP)
@@ -147,15+147,20 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                          struct options * old_opt;
                          if (optlen > 40 || optlen < 0)
                                return -EINVAL;
-                         err = verify_area(VERIFY_READ, optval, optlen);
-                         if (err)
-                               return err;
                          opt = kmalloc(sizeof(struct options)+((optlen+3)&~3), GFP_KERNEL);
                          if (!opt)
                                return -ENOMEM;
                          memset(opt, 0, sizeof(struct options));
                          if (optlen)
-                               copy_from_user(opt->__data, optval, optlen);
+                         {
+                                 err = copy_from_user(opt->__data, optval, optlen);
+                                 if (err)
+                                 {
+                                         kfree_s(opt, sizeof(struct options) + ((optlen+3)&~3));
+                                         return -EFAULT;
+                                 }
+                         }
+
                          while (optlen & 3)
                                opt->__data[optlen++] = IPOPT_END;
                          opt->optlen = optlen;
@@ -228,13+233,11 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        /*
                         *      Check the arguments are allowable
                         */
-
-                       err=verify_area(VERIFY_READ, optval, sizeof(addr));
-                       if(err)
-                               return err;
                                
-                       copy_from_user(&addr,optval,sizeof(addr));
-                       
+                       err = copy_from_user(&addr,optval,sizeof(addr));
+                       if (err)
+                               return -EFAULT; 
+
                        
                        /*
                         *      What address has been requested
@@ -278,11+281,9 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                         *      Check the arguments.
                         */
 
-                       err=verify_area(VERIFY_READ, optval, sizeof(mreq));
-                       if(err)
-                               return err;
-
-                       copy_from_user(&mreq,optval,sizeof(mreq));
+                       err = copy_from_user(&mreq,optval,sizeof(mreq));
+                       if (err)
+                               return -EFAULT; 
 
                        /* 
                         *      Get device for use later
@@ -333,11+334,9 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                         *      Check the arguments
                         */
                         
-                       err=verify_area(VERIFY_READ, optval, sizeof(mreq));
-                       if(err)
-                               return err;
-
-                       copy_from_user(&mreq,optval,sizeof(mreq));
+                       err = copy_from_user(&mreq,optval,sizeof(mreq));
+                       if (err)
+                               return -EFAULT; 
 
                        /*
                         *      Get device for use later 
@@ -399,10+398,9 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                                return -EPERM;
                        if(optlen>sizeof(tmp_fw) || optlen<1)
                                return -EINVAL;
-                       err=verify_area(VERIFY_READ,optval,optlen);
-                       if(err)
-                               return err;
-                       copy_from_user(&tmp_fw,optval,optlen);
+                       err = copy_from_user(&tmp_fw,optval,optlen);
+                       if (err)
+                               return -EFAULT; 
                        err=ip_fw_ctl(optname, &tmp_fw,optlen);
                        return -err;    /* -0 is 0 after all */
                        
@@ -417,10+415,9 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                                return -EPERM;
                        if(optlen>sizeof(tmp_fw) || optlen<1)
                                return -EINVAL;
-                       err=verify_area(VERIFY_READ,optval,optlen);
-                       if(err)
-                               return err;
-                       copy_from_user(&tmp_fw, optval,optlen);
+                       err = copy_from_user(&tmp_fw, optval,optlen);
+                       if (err)
+                               return -EFAULT; 
                        err=ip_acct_ctl(optname, &tmp_fw,optlen);
                        return -err;    /* -0 is 0 after all */
 #endif
@@ -458,9+455,7 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                        {
                                unsigned char optbuf[sizeof(struct options)+40];
                                struct options * opt = (struct options*)optbuf;
-                               err = verify_area(VERIFY_WRITE, optlen, sizeof(int));
-                               if (err)
-                                       return err;
+
                                cli();
                                opt->optlen = 0;
                                if (sk->opt)
@@ -468,12+463,8 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                                sti();
                                if (opt->optlen == 0) 
                                {
-                                       put_user(0, optlen);
-                                       return 0;
+                                       return put_user(0, optlen);
                                }
-                               err = verify_area(VERIFY_WRITE, optval, opt->optlen);
-                               if (err)
-                                       return err;
 /*
  * Now we should undo all the changes done by ip_options_compile().
  */
@@ -503,8+494,10 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                                                optptr[2] -= 4;
                                        }
                                }
-                               put_user(opt->optlen, optlen);
-                               copy_to_user(optval, opt->__data, opt->optlen);
+                               err = put_user(opt->optlen, optlen);
+                               if (!err)
+                                       err = copy_to_user(optval, opt->__data, opt->optlen);
+                               return err; 
                        }
                        return 0;
                case IP_TOS:
@@ -524,29+517,17 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                        val=sk->ip_mc_loop;
                        break;
                case IP_MULTICAST_IF:
-                       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-                       if(err)
-                               return err;
                        len=strlen(sk->ip_mc_name);
-                       err=verify_area(VERIFY_WRITE, optval, len);
-                       if(err)
-                               return err;
-                       put_user(len, optlen);
-                       copy_to_user((void *)optval,sk->ip_mc_name, len);
-                       return 0;
+                       err = put_user(len, optlen);
+                       if (!err)
+                               err = copy_to_user((void *)optval,sk->ip_mc_name, len);
+                       return err;
 #endif
                default:
                        return(-ENOPROTOOPT);
        }
-       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-       if(err)
-               return err;
-       put_user(sizeof(int), optlen);
-
-       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
-       if(err)
-               return err;
-       put_user(val,(int *) optval);
-
-       return(0);
+       err = put_user(sizeof(int), optlen);
+       if (err) 
+               return err; 
+       return put_user(val,(int *) optval);
 }
index 46197a9..99c0d33 100644 (file)
@@ -447,11+447,11 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
                                return -EOPNOTSUPP;
                        if(optlen!=sizeof(int))
                                return -ENOPROTOOPT;
-                       if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
-                               return err;
                        {
                                int opt;
-                               get_user(opt,(int *)optval);
+                               err = get_user(opt,(int *)optval);
+                               if (err) 
+                                       return err; 
                                if (opt != 1)
                                        return -ENOPROTOOPT;
                        }
@@ -468,9+468,9 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
                case MRT_DEL_VIF:
                        if(optlen!=sizeof(vif))
                                return -EINVAL;
-                       if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
-                               return err;
-                       copy_from_user(&vif,optval,sizeof(vif));
+                       err = copy_from_user(&vif,optval,sizeof(vif));
+                       if (err)
+                               return -EFAULT; 
                        if(vif.vifc_vifi > MAXVIFS)
                                return -ENFILE;
                        if(optname==MRT_ADD_VIF)
@@ -545,17+545,16 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
                 */
                case MRT_ADD_MFC:
                case MRT_DEL_MFC:
-                       err=verify_area(VERIFY_READ, optval, sizeof(mfc));
-                       if(err)
-                               return err;
-                       copy_from_user(&mfc,optval, sizeof(mfc));
-                       return ipmr_mfc_modify(optname, &mfc);
+                       err = copy_from_user(&mfc,optval, sizeof(mfc));
+                       return err ? -EFAULT : ipmr_mfc_modify(optname, &mfc);
                /*
                 *      Control PIM assert.
                 */
                case MRT_ASSERT:
                        if(optlen!=sizeof(int))
                                return -EINVAL;
+
+                       /* BUG BUG this is wrong IMHO -AK. */ 
                        if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
                                return err;
                        mroute_do_pim= (optval)?1:0;
@@ -583,18+582,19 @@ int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
        if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
                return -EOPNOTSUPP;
        
-       get_user(olr, optlen);
+       err = get_user(olr, optlen);
+       if (err)
+               return err; 
        if(olr!=sizeof(int))
                return -EINVAL;
-       err=verify_area(VERIFY_WRITE, optval,sizeof(int));
-       if(err)
-               return err;
-       put_user(sizeof(int),optlen);
+       err = put_user(sizeof(int),optlen);
+       if (err)
+               return err; 
        if(optname==MRT_VERSION)
-               put_user(0x0305,(int *)optval);
+               err = put_user(0x0305,(int *)optval);
        else
-               put_user(mroute_do_pim,(int *)optval);
-       return 0;
+               err = put_user(mroute_do_pim,(int *)optval);
+       return err;
 }
 
 /*
@@ -611,10+611,9 @@ int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
        switch(cmd)
        {
                case SIOCGETVIFCNT:
-                       err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
-                       if(err)
-                               return err;
-                       copy_from_user(&vr,(void *)arg,sizeof(vr));
+                       err = copy_from_user(&vr,(void *)arg,sizeof(vr));
+                       if (err)
+                               return -EFAULT; 
                        if(vr.vifi>=MAXVIFS)
                                return -EINVAL;
                        vif=&vif_table[vr.vifi];
@@ -624,17+623,19 @@ int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
                                vr.ocount=vif->pkt_out;
                                vr.ibytes=vif->bytes_in;
                                vr.obytes=vif->bytes_out;
-                               copy_to_user((void *)arg,&vr,sizeof(vr));
-                               return 0;
+                               err = copy_to_user((void *)arg,&vr,sizeof(vr));
+                               if (err)
+                                       err = -EFAULT;
+                               return err;
                        }
                        return -EADDRNOTAVAIL;
                case SIOCGETSGCNT:
-                       err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
-                       if(err)
-                               return err;
-                       copy_from_user(&sr,(void *)arg,sizeof(sr));
-                       copy_to_user((void *)arg,&sr,sizeof(sr));
-                       return 0;
+                       err = copy_from_user(&sr,(void *)arg,sizeof(sr));
+                       if (!err)
+                               err = copy_to_user((void *)arg,&sr,sizeof(sr));
+                       if (err)
+                               err = -EFAULT;
+                       return err;
                default:
                        return -EINVAL;
        }
index 6db0776..27107fa 100644 (file)
@@ -120,7+120,8 @@ static int packet_sendmsg(struct sock *sk, struct msghdr *msg, int len,
        struct device *dev;
        struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
        unsigned short proto=0;
-
+       int err;
+       
        /*
         *      Check the flags. 
         */
@@ -180,18+181,33 @@ static int packet_sendmsg(struct sock *sk, struct msghdr *msg, int len,
         
        skb->sk = sk;
        skb->free = 1;
-       memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
-       skb->arp = 1;           /* No ARP needs doing on this (complete) frame */
+       err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+       skb->arp = 1;   /* No ARP needs doing on this (complete) frame */
        skb->protocol = proto;
 
        /*
         *      Now send it
         */
 
-       if (dev->flags & IFF_UP) 
-               dev_queue_xmit(skb, dev, sk->priority);
+       if (err)
+       {
+               err = -EFAULT;
+       }
        else
+       {
+               if (!(dev->flags & IFF_UP))
+               {
+                       err = -ENODEV;
+               }
+       }
+       
+       if (err) 
+       {
                kfree_skb(skb, FREE_WRITE);
+               return err;
+       }
+               
+       dev_queue_xmit(skb, dev, sk->priority);
        return(len);
 }
 
@@ -436,7+452,13 @@ int packet_recvmsg(struct sock *sk, struct msghdr *msg, int len,
         
        copied = min(len, skb->len);
 
-       memcpy_toiovec(msg->msg_iov, skb->data, copied);        /* We can't use skb_copy_datagram here */
+       /* We can't use skb_copy_datagram here */
+       err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+       if (err)
+       {
+               return -EFAULT;
+       }
+
        sk->stamp=skb->stamp;
 
        /*
index 43d1d76..a97744e 100644 (file)
@@ -289,9+289,12 @@ static int rarp_req_set(struct arpreq *req)
        unsigned long ip;
        struct rtable *rt;
        struct device * dev;
+       int err; 
   
-       copy_from_user(&r, req, sizeof(r));
-  
+       err = copy_from_user(&r, req, sizeof(r));
+       if (err)
+               return -EFAULT;
+
        /*
         *      We only understand about IP addresses... 
         */
@@ -390,13+393,16 @@ static int rarp_req_get(struct arpreq *req)
        struct rarp_table *entry;
        struct sockaddr_in *si;
        unsigned long ip;
-
+       int err; 
+       
 /*
  *     We only understand about IP addresses...
  */
         
-       copy_from_user(&r, req, sizeof(r));
-  
+       err = copy_from_user(&r, req, sizeof(r));
+       if (err)
+               return -EFAULT; 
+
        if (r.arp_pa.sa_family != AF_INET)
                return -EPFNOSUPPORT;
   
@@ -430,8+436,7 @@ static int rarp_req_get(struct arpreq *req)
  *        Copy the information back
  */
   
-       copy_to_user(req, &r, sizeof(r));
-       return 0;
+       return copy_to_user(req, &r, sizeof(r));
 }
 
 
@@ -450,10+455,9 @@ int rarp_ioctl(unsigned int cmd, void *arg)
                case SIOCDRARP:
                        if (!suser())
                                return -EPERM;
-                       err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
-                       if(err)
-                               return err;
-                       copy_from_user(&r, arg, sizeof(r));
+                       err = copy_from_user(&r, arg, sizeof(r));
+                       if (err)
+                               return -EFAULT; 
                        if (r.arp_pa.sa_family != AF_INET)
                                return -EPFNOSUPPORT;
                        si = (struct sockaddr_in *) &r.arp_pa;
@@ -461,16+465,11 @@ int rarp_ioctl(unsigned int cmd, void *arg)
                        return 0;
 
                case SIOCGRARP:
-                       err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
-                       if(err)
-                               return err;
+
                        return rarp_req_get((struct arpreq *)arg);
                case SIOCSRARP:
                        if (!suser())
                                return -EPERM;
-                       err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
-                       if(err)
-                               return err;
                        return rarp_req_set((struct arpreq *)arg);
                default:
                        return -EINVAL;
index 4f1ac37..68852df 100644 (file)
@@ -161,18+161,22 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb, struct device *dev, __u32 sadd
  *     Callback support is trivial for SOCK_RAW
  */
   
-static void raw_getfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
+static int raw_getfrag(const void *p, __u32 saddr, char *to,
+                      unsigned int offset, unsigned int fraglen)
 {
-       copy_from_user(to, (const unsigned char *)p+offset, fraglen);
+       return copy_from_user(to, (const unsigned char *)p+offset, fraglen);
 }
 
 /*
  *     IPPROTO_RAW needs extra work.
  */
  
-static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
+static int raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
 {
-       copy_from_user(to, (const unsigned char *)p+offset, fraglen);
+       int err; 
+       err = copy_from_user(to, (const unsigned char *)p+offset, fraglen);
+       if (err)
+               return err; 
        if(offset==0)
        {
                struct iphdr *iph=(struct iphdr *)to;
@@ -189,6+193,7 @@ static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int of
                        iph->id = htons(ip_id_count++);
                iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
        }
+       return 0; 
 }
 
 static int raw_sendto(struct sock *sk, const unsigned char *from, 
@@ -283,11+288,17 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock
                buf=kmalloc(len, GFP_KERNEL);
                if(buf==NULL)
                        return -ENOBUFS;
-               memcpy_fromiovec(buf, msg->msg_iov, len);
-               fs=get_fs();
-               set_fs(get_ds());
-               err=raw_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
-               set_fs(fs);
+               err = memcpy_fromiovec(buf, msg->msg_iov, len);
+               if (!err)
+               {
+                       fs=get_fs();
+                       set_fs(get_ds());
+                       err=raw_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
+                       set_fs(fs);
+               }
+               else
+                       err = -EFAULT;
+               
                kfree_s(buf,len);
                return err;
        }
@@ -341,7+352,7 @@ int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
 
        copied = min(len, skb->len);
        
-       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
        sk->stamp=skb->stamp;
 
        /* Copy the address. */
@@ -351,7+362,7 @@ int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
                sin->sin_addr.s_addr = skb->daddr;
        }
        skb_free_datagram(sk, skb);
-       return (copied);
+       return err ? err : (copied);
 }
 
 
index d575016..c8a0eb4 100644 (file)
@@ -1696,10+1696,9 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)
                case SIOCDELRT:         /* Delete a route */
                        if (!suser())
                                return -EPERM;
-                       err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
+                       err = copy_from_user(&rt, arg, sizeof(struct rtentry));
                        if (err)
-                               return err;
-                       copy_from_user(&rt, arg, sizeof(struct rtentry));
+                               return -EFAULT; 
                        return (cmd == SIOCDELRT) ? ip_rt_kill(&rt) : ip_rt_new(&rt);
        }
 
index 24b877a..a6556bf 100644 (file)
@@ -658,7+658,6 @@ int tcp_select(struct sock *sk, int sel_type, select_table *wait)
 
 int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-       int err;
        switch(cmd)
        {
 
@@ -675,21+674,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        lock_sock(sk);
                        amount = tcp_readable(sk);
                        release_sock(sk);
-                       err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(int));
-                       if(err)
-                               return err;
-                       put_user(amount, (int *)arg);
-                       return(0);
+                       return put_user(amount, (int *)arg);
                }
                case SIOCATMARK:
                {
                        int answ = sk->urg_data && sk->urg_seq == sk->copied_seq;
-
-                       err = verify_area(VERIFY_WRITE,(void *) arg, sizeof(int));
-                       if (err)
-                               return err;
-                       put_user(answ,(int *) arg);
-                       return(0);
+                       return put_user(answ,(int *) arg);
                }
                case TIOCOUTQ:
                {
@@ -697,11+687,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 
                        if (sk->state == TCP_LISTEN) return(-EINVAL);
                        amount = sock_wspace(sk);
-                       err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(int));
-                       if(err)
-                               return err;
-                       put_user(amount, (int *)arg);
-                       return(0);
+                       return put_user(amount, (int *)arg);
                }
                default:
                        return(-EINVAL);
@@ -718,9+704,9 @@ extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int pus
        struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
        memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
        th->seq = htonl(sk->write_seq);
-#if 0
+
        th->psh =(push == 0) ? 1 : 0;
-#endif
+
        sk->bytes_rcv = 0;
        sk->ack_timed = 0;
        th->ack_seq = htonl(tp->rcv_nxt);
@@ -986,7+972,7 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov,
                        {
                                tmp += copy;
                        }
-                       
+
                        skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
        
                        /*
@@ -1106,6+1092,7 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
                        struct msghdr *msg, int len, int flags, 
                        int *addr_len)
 {
+       int err; 
        struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
        /*
@@ -1138,7+1125,7 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
                char c = sk->urg_data;
                if (!(flags & MSG_PEEK))
                        sk->urg_data = URG_READ;
-               memcpy_toiovec(msg->msg_iov, &c, 1);
+               err = memcpy_toiovec(msg->msg_iov, &c, 1);
                if(msg->msg_name)
                {
                        tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
@@ -1148,7+1135,7 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
                        *addr_len= tp->af_specific->sockaddr_len;
 
                release_sock(sk);
-               return 1;
+               return err ? -EFAULT : 1;
        }
        release_sock(sk);
 
@@ -1226,6+1213,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
        u32 peek_seq;
        volatile u32 *seq;      /* So gcc doesn't overoptimise */
        unsigned long used;
+       int err = 0; 
 
        /*
         *      This error should be checked.
@@ -1274,6+1262,8 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                        if (copied)
                                break;
                        copied = -ERESTARTSYS;
+                       if (nonblock)
+                               copied = -EAGAIN;
                        break;
                }
 
@@ -1398,13+1388,28 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                *seq += used;
 
                /*
-                *      This memcpy_tofs can sleep. If it sleeps and we
+                *      This memcpy_toiovec can sleep. If it sleeps and we
                 *      do a second read it relies on the skb->users to avoid
                 *      a crash when cleanup_rbuf() gets called.
                 */
 
-               memcpy_toiovec(msg->msg_iov,((unsigned char *)skb->h.th) +
-                       skb->h.th->doff*4 + offset, used);
+               /*
+                *      FIXME: should break out of the loop early when an
+                *      error occurs
+                */
+               
+               err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used);
+               
+               if (err)
+               {
+                       /*
+                        *      exception. bailout!
+                        */
+                       *seq -= err;
+                       skb->users--;
+                       return -EFAULT;
+               }
+
                copied += used;
                len -= used;
 
@@ -1414,7+1419,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                 *      but you'll just have to fix it neatly ;)
                 */
 
-               skb->users --;
+               skb->users--;
 
                if (after(sk->copied_seq,sk->urg_seq))
                        sk->urg_data = 0;
@@ -1824,17+1829,12 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
                default:
                        return(-ENOPROTOOPT);
        }
-       err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
-       if(err)
-               return err;
-       put_user(sizeof(int),(int *) optlen);
 
-       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
-       if(err)
-               return err;
-       put_user(val,(int *)optval);
+       err = put_user(sizeof(int),(int *) optlen);
+       if (!err)
+               err = put_user(val,(int *)optval);
 
-       return(0);
+       return err;
 }
 
 void tcp_set_keepalive(struct sock *sk, int val)
@@ -1849,6+1849,104 @@ void tcp_set_keepalive(struct sock *sk, int val)
        }
 }
 
+
+/*
+ *      This function returns the amount that we can raise the
+ *      usable window based on the following constraints
+ *  
+ *     1. The window can never be shrunk once it is offered (RFC 793)
+ *     2. We limit memory per socket
+ */
+
+
+unsigned short tcp_select_window(struct sock *sk)
+{
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       long free_space = sock_rspace(sk);
+       long window;
+       long cur_win;
+       long usable;
+       int mss = sk->mss;
+       
+       if (sk->window_clamp)
+       {
+               free_space = min(sk->window_clamp, free_space);
+               mss = min(sk->window_clamp, mss);
+       }
+       
+       /*
+        * compute the actual window i.e.
+        * old_window - received_bytes_on_that_win
+        */
+
+       cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd);
+       window  = tp->rcv_wnd;
+       
+       if ( cur_win < 0 )
+       {
+               cur_win = 0;
+               printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n",
+                      tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup);
+       }
+
+       /*
+        * RFC 1122:
+        * "the suggested [SWS] avoidance algoritm for the receiver is to keep
+        *  RECV.NEXT + RCV.WIN fixed until:
+        *  RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
+        *
+        * i.e. don't raise the right edge of the window until you can't raise
+        * it MSS bytes
+        */
+
+       /*
+        * It would be a good idea if it didn't break header prediction.
+        * and BSD made the header predition standard...
+        * It expects the same value in the header i.e. th->window to be
+        * constant
+        */
+
+       usable = free_space - cur_win;
+       if (usable < 0)
+       {
+               usable = 0;
+       }
+
+       if ( window <  usable )
+       {
+               /*
+                *      Window is not blocking the sender
+                *      and we have enought free space for it
+                */
+
+               if (cur_win > (sk->mss << 1))
+                       goto out;
+       }
+
+               
+       if (window >= usable)
+       {
+               /*
+                *      We are offering too much, cut it down... 
+                *      but don't shrink the window
+                */
+               
+               window = max(usable, cur_win);
+       }
+       else
+       {       
+               if ((usable - window) >= mss)
+               {
+                       window += mss;
+               }
+       }
+
+  out:
+       tp->rcv_wnd = window;
+       tp->rcv_wup = tp->rcv_nxt;
+       return window;
+}
+
 /*
  * Local variables:
  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -c -o tcp.o tcp.c"
index d9188b1..7ce6f06 100644 (file)
@@ -194,11+194,18 @@ static int tcp_reset(struct sock *sk, struct sk_buff *skb)
        /*
         *      We want the right error as BSD sees it (and indeed as we do).
         */
-       sk->err = ECONNRESET;
-       if (sk->state == TCP_SYN_SENT)
-               sk->err = ECONNREFUSED;
-       if (sk->state == TCP_CLOSE_WAIT)
-               sk->err = EPIPE;
+       switch (sk->state) {
+               case TCP_TIME_WAIT:
+                       break;
+               case TCP_SYN_SENT:
+                       sk->err = ECONNREFUSED;
+                       break;
+               case TCP_CLOSE_WAIT:
+                       sk->err = EPIPE;
+                       break;
+               default:
+                       sk->err = ECONNRESET;
+       }
 #ifdef CONFIG_TCP_RFC1337
        /*
         *      Time wait assassination protection [RFC1337]
index 4c074ed..59d6c28 100644 (file)
@@ -227,14+227,14 @@ struct udpfakehdr
  *     for direct user->board I/O transfers. That one will be fun.
  */
  
-static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) 
+static int udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) 
 {
        struct udpfakehdr *ufh = (struct udpfakehdr *)p;
        const char *src;
        char *dst;
        unsigned int len;
 
-       if (offset) 
+       if (offset)
        {
                len = fraglen;
                src = ufh->from+(offset-sizeof(struct udphdr));
@@ -258,6+258,7 @@ static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offs
                        ufh->uh.check = -1;
                memcpy(to, ufh, sizeof(struct udphdr));
        }
+       return 0;
 }
 
 /*
@@ -267,12+268,13 @@ static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offs
  *     this is a valid decision.
  */
  
-static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) 
+static int udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) 
 {
        struct udpfakehdr *ufh = (struct udpfakehdr *)p;
        const char *src;
        char *dst;
        unsigned int len;
+       int err; 
 
        if (offset) 
        {
@@ -286,9+288,10 @@ static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned in
                src = ufh->from;
                dst = to+sizeof(struct udphdr);
        }
-       copy_from_user(dst,src,len);
+       err = copy_from_user(dst,src,len);
        if (offset == 0) 
                memcpy(to, ufh, sizeof(struct udphdr));
+       return err; 
 }
 
 
@@ -458,11+461,16 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock,
                buf=kmalloc(len, GFP_KERNEL);
                if(buf==NULL)
                        return -ENOBUFS;
-               memcpy_fromiovec(buf, msg->msg_iov, len);
-               fs=get_fs();
-               set_fs(get_ds());
-               err=udp_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
-               set_fs(fs);
+               err = memcpy_fromiovec(buf, msg->msg_iov, len);
+               if (err)
+                       err = -EFAULT;
+               if (!err)
+               {
+                       fs=get_fs();
+                       set_fs(get_ds());
+                       err=udp_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
+                       set_fs(fs);
+               }
                kfree_s(buf,len);
                return err;
        }
@@ -474,7+482,6 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock,
  
 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-       int err;
        switch(cmd) 
        {
                case TIOCOUTQ:
@@ -483,12+490,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 
                        if (sk->state == TCP_LISTEN) return(-EINVAL);
                        amount = sock_wspace(sk);
-                       err=verify_area(VERIFY_WRITE,(void *)arg,
-                                       sizeof(unsigned long));
-                       if(err)
-                               return(err);
-                       put_user(amount, (int *)arg);
-                       return(0);
+                       return put_user(amount, (int *)arg);
                }
 
                case TIOCINQ:
@@ -507,12+509,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                                 */
                                amount = skb->len-sizeof(struct udphdr);
                        }
-                       err=verify_area(VERIFY_WRITE,(void *)arg,
-                                               sizeof(unsigned long));
-                       if(err)
-                               return(err);
-                       put_user(amount, (int *)arg);
-                       return(0);
+                       return put_user(amount, (int *)arg);
                }
 
                default:
@@ -559,7+556,9 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
         *      FIXME : should use udp header size info value 
         */
         
-       skb_copy_datagram_iovec(skb,sizeof(struct udphdr),msg->msg_iov,copied);
+       er = skb_copy_datagram_iovec(skb,sizeof(struct udphdr),msg->msg_iov,copied);
+       if (er)
+               return er; 
        sk->stamp=skb->stamp;
 
        /* Copy the address. */
index e16ce2f..e11c5ee 100644 (file)
@@ -13,6+13,7 @@ O_OBJS   := af_inet6.o ipv6_output.o ipv6_input.o addrconf.o sit.o \
            protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
            exthdrs.o sysctl_net_ipv6.o datagram.o
 
+MOD_LIST_NAME := IPV6_MODULES
 M_OBJS   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
index ab2b453..e412e85 100644 (file)
@@ -774,7+774,7 @@ void addrconf_prefix_rcv(struct device *dev, u8 *opt, int len)
 
 }
 
-static void addrconf_ifdown(struct device *dev)
+static int addrconf_ifdown(struct device *dev)
 {
        struct inet6_dev *idev, **bidev;
        struct inet6_ifaddr *ifa, **bifa;
@@ -796,8+796,9 @@ static void addrconf_ifdown(struct device *dev)
 
        if (idev == NULL)
        {
-               printk(KERN_DEBUG "addrconf_ifdown: device not found\n"); 
-               return;
+               printk(KERN_DEBUG "addrconf_ifdown: device not found\n");
+               end_bh_atomic();
+               return -ENODEV;
        }
        
        /*
@@ -828,6+829,7 @@ static void addrconf_ifdown(struct device *dev)
 
        kfree(idev);
        end_bh_atomic();
+       return 0;
 }
 
 /*
@@ -1024,9+1026,12 @@ int addrconf_notify(struct notifier_block *this, unsigned long event,
                 *      Remove all addresses from this interface
                 *      and take the interface out of the list.
                 */
-               addrconf_ifdown(dev);
-               rt6_ifdown(dev);
-               rt6_sndmsg(RTMSG_NEWDEVICE, NULL, NULL, 0, 0, dev->name, 0);
+               if (addrconf_ifdown(dev) == 0)
+               {
+                       rt6_ifdown(dev);
+                       rt6_sndmsg(RTMSG_NEWDEVICE, NULL, NULL, 0, 0,
+                                  dev->name, 0);
+               }
 
                break;
        }
index 964a672..76124d2 100644 (file)
@@ -107,7+107,7 @@ static int inet6_create(struct socket *sock, int protocol)
        struct proto *prot;
        int err;
 
-       sk = (struct sock *) kmalloc(sizeof(*sk), GFP_KERNEL);
+       sk = sk_alloc(GFP_KERNEL);
        if (sk == NULL) 
                return(-ENOBUFS);
 
index 1d6da70..f959189 100644 (file)
  *      2 of the License, or (at your option) any later version.
  */
 
+/*
+ *     Changes:
+ *
+ *     Andi Kleen              :       exception handling
+ */
+
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -95,7+101,7 @@ struct icmpv6_msg {
  *     not static because it's needed in ndisc.c
  */
 
-static void icmpv6_getfrag(const void *data, struct in6_addr *saddr, 
+static int icmpv6_getfrag(const void *data, struct in6_addr *saddr, 
                           char *buff, unsigned int offset, unsigned int len)
 {
        struct icmpv6_msg *msg = (struct icmpv6_msg *) data;
@@ -114,7+120,7 @@ static void icmpv6_getfrag(const void *data, struct in6_addr *saddr,
                                         offset - sizeof(struct icmpv6hdr), 
                                         buff, len, msg->csum);
                msg->csum = csum;
-               return;
+               return 0;
        }
 
        csum = csum_partial_copy((void *) &msg->icmph, buff,
@@ -128,6+134,7 @@ static void icmpv6_getfrag(const void *data, struct in6_addr *saddr,
 
        icmph->checksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
                                          IPPROTO_ICMPV6, csum);
+       return 0; 
 }
 
 /*
index baf030a..7f82dba 100644 (file)
  *      2 of the License, or (at your option) any later version.
  */
 
+/*
+ *     Changes:
+ *
+ *     Andi Kleen              :       exception handling
+ */
 
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -440,7+445,7 @@ int ipv6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
        int     pktlength;
        int     pmtu = 0;
        int     rt_flags = 0;
-       
+       int     error; 
        
        if (opt && opt->srcrt)
        {
@@ -568,8+573,6 @@ int ipv6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
 
        if (pktlength <= pmtu) 
        {
-               int error;
-
                struct sk_buff *skb =
                        sock_alloc_send_skb(sk, pktlength+15+
                                            dev->hard_header_len,
@@ -624,14+627,22 @@ int ipv6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
                }
                        
                skb_put(skb, length);
-               getfrag(data, &hdr->saddr,
-                       ((char *) hdr) + (pktlength - length), 0, length);
+               error = getfrag(data, &hdr->saddr,
+                               ((char *) hdr) + (pktlength - length),
+                               0, length);
                        
-               ipv6_statistics.Ip6OutRequests++;
-               (*output_method)(skb, (struct rt6_info *) dc);
+               if (!error) 
+               {
+                       ipv6_statistics.Ip6OutRequests++;
+                       (*output_method)(skb, (struct rt6_info *) dc);
+               } else
+               {
+                       error = -EFAULT;
+                       kfree_skb(skb, FREE_WRITE);                     
+               }
 
                dev_unlock_list();
-               return 0;
+               return error;
        }
        else
        {
@@ -763,31+774,52 @@ int ipv6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
 
                fhdr_dist = (unsigned char *) fhdr - last_skb->data;
 
-               getfrag(data, &hdr->saddr, last_skb->tail, nfrags * frag_len, 
-                       last_len);
+               error = getfrag(data, &hdr->saddr, last_skb->tail,
+                               nfrags * frag_len, last_len);
                
-               while (nfrags--)
-               {
-                       struct sk_buff *skb;
-
-                       struct frag_hdr *fhdr2;
-
-                       printk(KERN_DEBUG "sending frag %d\n", nfrags);
-                       skb = skb_copy(last_skb, sk->allocation);
-
-                       fhdr2 = (struct frag_hdr *) (skb->data + fhdr_dist);
-                       /* more flag on */
-                       fhdr2->frag_off = ntohs(nfrags * frag_len + 1);
-
-                       /* if (nfrags == 0)
-                          put rest of headers
-                          */
-
-                       getfrag(data, &hdr->saddr, skb_put(skb, frag_len), 
-                               nfrags * frag_len, frag_len);
+               if (!error)
+               {       
+                       while (nfrags--)
+                       {
+                               struct sk_buff *skb;
+                       
+                               struct frag_hdr *fhdr2;
+                               
+                               printk(KERN_DEBUG "sending frag %d\n", nfrags);
+                               skb = skb_copy(last_skb, sk->allocation);
+                               
+                               fhdr2 = (struct frag_hdr *)
+                                       (skb->data + fhdr_dist);
+                               
+                               /* more flag on */
+                               fhdr2->frag_off = ntohs(nfrags * frag_len + 1);
+                               
+                               /*
+                                *      FIXME:
+                                *      if (nfrags == 0)
+                                *      put rest of headers
+                                */
+                               
+                               error = getfrag(data, &hdr->saddr,
+                                               skb_put(skb, frag_len), 
+                                               nfrags * frag_len, frag_len);
+                       
+                               if (error)
+                               {
+                                       kfree_skb(skb, FREE_WRITE);
+                                       break;
+                               }
+
+                               ipv6_statistics.Ip6OutRequests++;
+                               (*output_method)(skb, (struct rt6_info *) dc);
+                       }
+               }
 
-                       ipv6_statistics.Ip6OutRequests++;
-                       (*output_method)(skb, (struct rt6_info *) dc);
+               if (error)
+               {
+                       kfree_skb(last_skb, FREE_WRITE);
+                       dev_unlock_list();
+                       return -EFAULT;
                }
 
                printk(KERN_DEBUG "sending last frag \n");
index ab6697e..7ae8308 100644 (file)
@@ -164,10+164,6 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
        {
                struct in6_addr addr;
 
-               err=verify_area(VERIFY_READ, optval, sizeof(struct in6_addr));
-               if(err)
-                       return err;
-
                err = copy_from_user(&addr, optval, sizeof(struct in6_addr));
                if(err)
                        return -EFAULT;
index cab6219..2b819c2 100644 (file)
@@ -124,9+124,12 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        
        copied = min(len, skb->tail - skb->h.raw);
        
-       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
        sk->stamp=skb->stamp;
 
+       if (err)
+               return err;
+
        /* Copy the address. */
        if (sin6) 
        {
@@ -166,15+169,15 @@ struct rawv6_fakehdr {
        struct in6_addr *daddr;
 };
 
-static void rawv6_getfrag(const void *data, struct in6_addr *saddr, 
+static int rawv6_getfrag(const void *data, struct in6_addr *saddr, 
                          char *buff, unsigned int offset, unsigned int len)
 {
        struct iovec *iov = (struct iovec *) data;
 
-       memcpy_fromiovecend(buff, iov, offset, len);
+       return memcpy_fromiovecend(buff, iov, offset, len);
 }
 
-static void rawv6_frag_cksum(const void *data, struct in6_addr *addr,
+static int rawv6_frag_cksum(const void *data, struct in6_addr *addr,
                             char *buff, unsigned int offset, 
                             unsigned int len)
 {
@@ -220,6+223,7 @@ static void rawv6_frag_cksum(const void *data, struct in6_addr *addr,
                        printk(KERN_DEBUG "icmp: cksum offset too big\n");
                }
        }       
+       return 0; 
 }
 
 
@@ -354,8+358,10 @@ static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
 
        switch (optname) {
                case ICMPV6_FILTER:
-                       copy_from_user(&opt->filter, optval,
+                       err = copy_from_user(&opt->filter, optval,
                                       sizeof(struct icmp6_filter));
+                       if (err)
+                               err = -EFAULT;
                        break;
                default:
                        err = -ENOPROTOOPT;
index 92ea071..7ec7a00 100644 (file)
@@ -172,7+172,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        int copied = 0;
        int truesize;
        struct sk_buff *skb;
-       int er;
+       int err;
        
 
        /*
@@ -187,9+187,9 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
         *      the finished NET3, it will do _ALL_ the work!
         */
                
-       skb = skb_recv_datagram(sk, flags, noblock, &er);
+       skb = skb_recv_datagram(sk, flags, noblock, &err);
        if(skb==NULL)
-               return er;
+               return err;
   
        truesize = skb->tail - skb->h.raw - sizeof(struct udphdr);
        copied = min(len, truesize);
@@ -198,7+198,11 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
         *      FIXME : should use udp header size info value 
         */
         
-       skb_copy_datagram_iovec(skb,sizeof(struct udphdr),msg->msg_iov,copied);
+       err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), 
+                                     msg->msg_iov, copied);
+       if (err)
+               return err; 
+       
        sk->stamp=skb->stamp;
 
        /* Copy the address. */
@@ -428,8+432,8 @@ struct udpv6fakehdr
  *     with checksum
  */
 
-static void udpv6_getfrag(const void *data, struct in6_addr *addr,
-                         char *buff, unsigned int offset, unsigned int len)
+static int udpv6_getfrag(const void *data, struct in6_addr *addr,
+                        char *buff, unsigned int offset, unsigned int len)
 {
        struct udpv6fakehdr *udh = (struct udpv6fakehdr *) data;
        char *dst;
@@ -479,6+483,7 @@ static void udpv6_getfrag(const void *data, struct in6_addr *addr,
 
                memcpy(buff, udh, sizeof(struct udphdr));
        }
+       return 0;
 }
 
 static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen, 
index 855bac7..0a636dd 100644 (file)
@@ -141,8+141,7 @@ ipxcfg_get_config_data(ipx_config_data *arg)
        
        vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
        vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
-       copy_to_user(arg, &vals, sizeof(vals));
-       return 0;
+       return copy_to_user(arg, &vals, sizeof(vals));
 }
 
 
@@ -1062,7+1061,8 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
                        struct sockaddr_ipx *sipx;
                        ipx_interface *ipxif;
                        struct device *dev;
-
+                       int err;
+                       
                        if (copy_from_user(&ifr,arg,sizeof(ifr)))
                                return -EFAULT;
                        sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
@@ -1075,9+1075,10 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
                        sipx->sipx_family=AF_IPX;
                        sipx->sipx_network=ipxif->if_netnum;
                        memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
-                       if (copy_to_user(arg,&ifr,sizeof(ifr)))
+                       err = copy_to_user(arg,&ifr,sizeof(ifr));
+                       if (err)
                                return -EFAULT;
-                       return 0;
+                       return err;
                }
                case SIOCAIPXITFCRT: {
                        int err, val;
@@ -1333,7+1334,12 @@ static int ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, struc
        memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
        ipx->ipx_dest.sock=usipx->sipx_port;
 
-       memcpy_fromiovec(skb_put(skb,len),iov,len);
+       err = memcpy_fromiovec(skb_put(skb,len),iov,len);
+       if (err) 
+       {
+               kfree_skb(skb, FREE_WRITE);
+               return -EFAULT; 
+       }       
 
        /*
         *      Apply checksum. Not allowed on 802.3 links.
@@ -1384,13+1390,11 @@ static int ipxrtr_ioctl(unsigned int cmd, void *arg)
        int err;
        struct rtentry rt;      /* Use these to behave like 'other' stacks */
        struct sockaddr_ipx *sg,*st;
-
-       err=verify_area(VERIFY_READ,arg,sizeof(rt));
-       if(err)
-               return err;
                
-       copy_from_user(&rt,arg,sizeof(rt));
-       
+       err = copy_from_user(&rt,arg,sizeof(rt));
+       if (err)
+               return -EFAULT; 
+
        sg=(struct sockaddr_ipx *)&rt.rt_gateway;
        st=(struct sockaddr_ipx *)&rt.rt_dst;
        
@@ -1677,14+1681,10 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
                default:
                        return -EOPNOTSUPP;
        }
-       err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
-       if(err)
-               return err;
-       put_user(sizeof(int), optlen);
-       err=verify_area(VERIFY_WRITE,optval,sizeof(int));
-       if (err) return err;
-       put_user(val, (int *)optval);
-       return(0);
+       err = put_user(sizeof(int), optlen);
+       if (!err)
+               err = put_user(val, (int *)optval);
+       return err;
 }
 
 static int ipx_listen(struct socket *sock, int backlog)
@@ -2168,8+2168,11 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int no
        ipx = (ipx_packet *)(skb->h.raw);
        truesize=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet);
        copied = (truesize > size) ? size : truesize;
-       skb_copy_datagram_iovec(skb,sizeof(struct ipx_packet),msg->msg_iov,copied);
+       err = skb_copy_datagram_iovec(skb,sizeof(struct ipx_packet),msg->msg_iov,copied);
        
+       if (err)
+               return err; 
+
        if(sipx)
        {
                sipx->sipx_family=AF_IPX;
@@ -2203,25+2206,17 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
        switch(cmd)
        {
                case TIOCOUTQ:
-                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
-                       if(err)
-                               return err;
                        amount=sk->sndbuf-sk->wmem_alloc;
                        if(amount<0)
                                amount=0;
-                       put_user(amount, (int *)arg);
-                       return 0;
+                       return put_user(amount, (int *)arg);
                case TIOCINQ:
                {
                        struct sk_buff *skb;
                        /* These two are safe on a single CPU system as only user tasks fiddle here */
                        if((skb=skb_peek(&sk->receive_queue))!=NULL)
                                amount=skb->len-sizeof(struct ipx_packet);
-                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
-                       if(err)
-                               return err;
-                       put_user(amount, (int *)arg);
-                       return 0;
+                       return put_user(amount, (int *)arg);
                }
                case SIOCADDRT:
                case SIOCDELRT:
@@ -2237,23+2232,21 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
                        return(ipxitf_ioctl(cmd,(void *)arg));
                case SIOCIPXCFGDATA: 
                {
-                       err=verify_area(VERIFY_WRITE,(void *)arg,
-                               sizeof(ipx_config_data));
-                       if(err) return err;
                        return(ipxcfg_get_config_data((void *)arg));
                }
                case SIOCGSTAMP:
+               {
+                       int ret = -EINVAL;
                        if (sk)
                        {
                                if(sk->stamp.tv_sec==0)
                                        return -ENOENT;
-                               err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
-                               if(err)
-                                       return err;
-                               copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
-                               return 0;
+                               ret = copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
+                               if (ret)
+                                       ret = -EFAULT;
                        }
-                       return -EINVAL;
+                       return 0;
+               }
                case SIOCGIFDSTADDR:
                case SIOCSIFDSTADDR:
                case SIOCGIFBRDADDR:
index c496971..f1a5c90 100644 (file)
@@ -85,12+85,13 @@ static int netlink_select(struct inode *inode, struct file *file, int sel_type,
 static long netlink_write(struct inode * inode, struct file * file,
                          const char * buf, unsigned long count)
 {
+       int err; 
        unsigned int minor = MINOR(inode->i_rdev);
        struct sk_buff *skb;
        skb=alloc_skb(count, GFP_KERNEL);
        skb->free=1;
-       copy_from_user(skb_put(skb,count),buf, count);
-       return (netlink_handler[minor])(skb);
+       err = copy_from_user(skb_put(skb,count),buf, count);
+       return err ? -EFAULT : (netlink_handler[minor])(skb);
 }
 
 /*
@@ -100,6+101,7 @@ static long netlink_write(struct inode * inode, struct file * file,
 static long netlink_read(struct inode * inode, struct file * file, char * buf,
                         unsigned long count)
 {
+       int err; 
        unsigned int minor = MINOR(inode->i_rdev);
        struct sk_buff *skb;
        cli();
@@ -121,9+123,9 @@ static long netlink_read(struct inode * inode, struct file * file, char * buf,
        sti();
        if(skb->len<count)
                count=skb->len;
-       copy_to_user(buf,skb->data,count);
+       err = copy_to_user(buf,skb->data,count);
        kfree_skb(skb, FREE_READ);
-       return count;
+       return err ? -EFAULT : count;
 }
 
 static loff_t netlink_lseek(struct inode * inode, struct file * file,
index f4b3a28..533fa8a 100644 (file)
@@ -159,8+159,7 @@ int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen)
                if(copy_to_user(uaddr,kaddr,len))
                        return -EFAULT;
        }
-       put_user(len, ulen);
-       return 0;
+       return put_user(len, ulen);
 }
 
 /*
@@ -649,17+648,14 @@ asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2
        sock1->state = SS_CONNECTED;
        sock2->state = SS_CONNECTED;
 
-       er=verify_area(VERIFY_WRITE, usockvec, sizeof(usockvec));
-       if(er)
-       {
+       er = put_user(fd1, &usockvec[0]); 
+       if (!er) 
+               er = put_user(fd2, &usockvec[1]);
+       if (er) {
                sys_close(fd1);
                sys_close(fd2);
-               return er;
        }
-       put_user(fd1, &usockvec[0]);
-       put_user(fd2, &usockvec[1]);
-
-       return(0);
+       return er;
 }
 
 
@@ -1133,12+1129,8 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned int flags)
        if(sock->ops->sendmsg==NULL)
                return -EOPNOTSUPP;
 
-
-       err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr));
-       if(err)
-               return err;
-
-       copy_from_user(&msg_sys,msg,sizeof(struct msghdr));
+       if ((err = copy_from_user(&msg_sys,msg,sizeof(struct msghdr))))
+               return -EFAULT; 
 
        /* do not move before msg_sys is valid */
        if(msg_sys.msg_iovlen>UIO_MAXIOV)
@@ -1200,11+1192,8 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
        if (!(sock = sockfd_lookup(fd, NULL)))
                return(-ENOTSOCK);
        
-       err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr));
-       if(err)
-               return err;
-
-       copy_from_user(&msg_sys,msg,sizeof(struct msghdr));
+       if ((err = copy_from_user(&msg_sys,msg,sizeof(struct msghdr))))
+               return -EFAULT; 
 
        if(msg_sys.msg_iovlen>UIO_MAXIOV)
                return -EINVAL;
@@ -1240,19+1229,24 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
        if(len<0)
                return len;
 
-       if (uaddr != NULL) {
+       if (uaddr != NULL)
+       {
                err = move_addr_to_user(addr, addr_len, uaddr, uaddr_len);
-               if (err)
-                       return err;
        }
 
        if (msg_sys.msg_control)
        {
-               copy_to_user(usr_msg_ctl, krn_msg_ctl, msg_sys.msg_controllen);
-               kfree(krn_msg_ctl);
+               if (!err)
+               {
+                       int ret;
+                       ret = copy_to_user(usr_msg_ctl, krn_msg_ctl,
+                                          msg_sys.msg_controllen);
+                       err = -EFAULT;
+               }
+               kfree(krn_msg_ctl);             
        }
 
-       return len;
+       return err ? err : len;
 }
 
 
@@ -1285,7+1279,6 @@ int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 asmlinkage int sys_socketcall(int call, unsigned long *args)
 {
-       int er;
        unsigned char nargs[18]={0,3,3,3,2,3,3,3,
                                 4,4,4,6,6,2,5,5,3,3};
        unsigned long a[6];
@@ -1294,10+1287,8 @@ asmlinkage int sys_socketcall(int call, unsigned long *args)
        if(call<1||call>SYS_RECVMSG)
                return -EINVAL;
                
-       er=verify_area(VERIFY_READ, args, nargs[call] * sizeof(unsigned long));
-       if(er)
-               return er;
-       copy_from_user(a, args, nargs[call] * sizeof(unsigned long));
+       if ((copy_from_user(a, args, nargs[call] * sizeof(unsigned long))))
+               return -EFAULT;
                
        a0=a[0];
        a1=a[1];
index e21c3e0..2361efb 100644 (file)
@@ -925,7+925,15 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                        }
                        return err;
                }
-               size=skb_tailroom(skb);         /* If we dropped back on a limit then our skb is smaller */
+
+               /*
+                *      If you pass two values to the sock_alloc_send_skb
+                *      it tries to grab the large buffer with GFP_BUFFER
+                *      (which can fail easily), and if it fails grab the
+                *      fallback size buffer which is under a page and will
+                *      succeed. [Alan]
+                */
+               size = min(size, skb_tailroom(skb));
 
                skb->sk=sk;
                skb->free=1;
@@ -1024,6+1032,7 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
        struct iovec *iov=msg->msg_iov;
        struct cmsghdr *cm=NULL;
        int ct=msg->msg_iovlen;
+       int err = 0;
 
        if(flags&MSG_OOB)
                return -EOPNOTSUPP;
@@ -1098,8+1107,13 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                        }
 
                        num=min(skb->len,len-done);
-                       copy_to_user(sp, skb->data, num);
+                       err = copy_to_user(sp, skb->data, num);
 
+                       if (err)
+                       {
+                               goto out;
+                       }
+                       
                        if (skb->h.filp!=NULL)
                                unix_detach_fds(skb,cm);
 
@@ -1121,7+1135,7 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
 out:
        up(&sk->protinfo.af_unix.readsem);
 
-       return copied;
+       return err ? -EFAULT : copied;
 }
 
 static int unix_shutdown(struct socket *sock, int mode)
@@ -1161,34+1175,28 @@ static int unix_select(struct socket *sock,  int sel_type, select_table *wait)
 static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        unix_socket *sk=sock->data;
-       int err;
        long amount=0;
                        
        switch(cmd)
        {
        
                case TIOCOUTQ:
-                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
-                       if(err)
-                               return err;
                        amount=sk->sndbuf-sk->wmem_alloc;
                        if(amount<0)
                                amount=0;
-                       put_user(amount, (int *)arg);
-                       return 0;
+                       return put_user(amount, (int *)arg);
                case TIOCINQ:
                {
                        struct sk_buff *skb;
                        if(sk->state==TCP_LISTEN)
                                return -EINVAL;
-                       /* These two are safe on a single CPU system as only user tasks fiddle here */
+                       /*
+                        *      These two are safe on a single CPU system as
+                        *      only user tasks fiddle here
+                        */
                        if((skb=skb_peek(&sk->receive_queue))!=NULL)
                                amount=skb->len;
-                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
-                       if(err)
-                               return err;
-                       put_user(amount, (int *)arg);
-                       return 0;
+                       return put_user(amount, (int *)arg);
                }
 
                default:
close