Commit 16c82539 authored by Linus Torvalds's avatar Linus Torvalds

pre-patch-2.1.131-3

Ok,
 I've made a new pre-patch-2.1.131-3.

The basic problem (that Alexander Viro correctly diagnosed) is that the
inode locking was horribly and subtly wrong for the case of a "rmdir()"
call. What rmdir() did was essentially something like

 - VFS: lock the directory that contains the directory to remove
   (this is normal and required to make sure that the name updates are
   completely atomic - so removing or adding anything requires you to hold
   the lock on the directory that contains the removee/addee)
 - low-level filesystem: lock the directory you're going to remove, in
   order to atomically check that it's empty.

So far so good, the above makes tons of sense. HOWEVER, the problem is
fairly obvious if anybody before Alexander had actually bothered to think
about it: when we hold two locks, we had better make sure that we get the
locks in the right order, or we may end up deadlocked with two (or more)
processes getting the locks in the wrong order and waiting on each other.

Now, if it was only rmdir(), things would be fine, because the directory
hierarchy itself imposes a lock order for rmdir(). But we have another
case that needs to lock two directories: "rename()". And that one doesn't
have the same kind of obvious order, and uses a different way to order the
two locks it gets. BOOM.

As far as I can tell, this is a problem in 2.0.x too, but while it's a
potential really nasty DoS-opening, it does have the saving grace that the
window to trigger it is really really small. I don't know if you can
actually make an exploit for it that has any real chance of hitting it,
but it's at least conceptually possible.

Now, the only sane fix was to actually make the VFS layer do all the
locking for rmdir(), and thus let the VFS layer make sure the order is
correct, so that low-level filesystems don't need to worry their pretty
heads. I tried to do that in the previous pre-patch, and it worked well
for ext2, but not all that much else. The problem was that too many
filesystems "knew" what the rmdir() downcall used to do. Oh, well.

Anyway, I've fixed the low-level filesystems as far as I can tell, and the
end result is a much cleaner interface (and one less bug). But it's an
interface change at a fairly late date, and while the fixes to smbfs etc
looked for the most part obvious, I haven't been able to test them, so
I've done most of them "blind".

Sadly, this bug couldn't just be glossed over, because a normal user could
(by knowing the exact right incantation) force tons of unkillable
processes that held critical filesystem resources (any lookup on a
directory that was locked would in turn also lock up). So I'd ask people
who have done filesystems for Linux to look over my changes, and if the
filesystems are not part of the standard distribution please look over
your own locally maintained fs code. I think we can ignore 2.0.x by virtue
of it probably being virtually impossible to trigger. I'll leave the
decision up to Alan.

Most specially, I'd like to have people who use/maintain vfat and umsdos
filesystems to test out that I actually made those filesystems happy with
my changes. The other filesystems were more straightforward.

Oh, and thanks to Alexander. Not that I really needed another bug to fix,
but it feels good to plug holes.

                        Linus

The change is basically:
 - the VFS layer locks the directory to be removed for you (as opposed to
   just the directory that contains the directory to be removed as it used
   to). A lot of filesystems didn't actually do this, and it is required,
   because otherwise the test for an empty directory may be subverted by a
   clever hacker.
 - the VFS layer will have done a dcache "prune" operation on the
   directory, and if there were no other uses for that dcache entry, it
   will have done a "d_drop()" on it too.
 - the above essentially means that any filesystem can do a
        if (!list_empty(&dentry->d_hash))
                return -EBUSY;
   to test whether there are other users of this directory. No need to do
   any extra pruning etc - if it's been dropped there won't be any new
   users of the dentry afterwards, so there are no races. So after doing
   the above test you know that you'll have exclusive access to the dentry
   forever.
   Most notably, the low-level filesystem should _not_ look at the
   dentry->d_count member to see how many users there are. The VFS layer
   currently artificially raises the dentry count to make sure
   "d_delete()" doesn't get rid of the inode early.
 - however: traditional local UNIX-type filesystems tend to want to allow
   removing of the directory even if it is in use by something else. This
   requires that the inode be accessible even after the rmdir() - even
   though it doesn't necessarily need to actually _do_ anything.
   For a normal UNIX-like filesystem this tends to be trivial and quite
   automatic behaviour, but you need to think about whether your
   filesystem is of the kind where the inode stays around even after the
   delete until we locally do the final "iput()". For example, on
   networked filesystems this is generally not true, simply because the
   server will have de-allocated the inode even if we still have a
   reference to it locally.
parent b468356b
......@@ -8492,13 +8492,14 @@ CONFIG_JOYSTICK
The module will be called joystick.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
Classic PC analog joysticks
Classic PC analog joysticks and gamepads
CONFIG_JOY_ANALOG
Say Y here if you have an analog joystick or gamepad that connects
to the PC gameport. This supports many different types, including
joysticks with throttle control, and with CHF / FCS / 6-button
extensions. For more information on how to use the driver please
read Documentation/joystick.txt
joysticks with throttle control, with rudders, or with extensions
like additional hats and buttons compatible with CH Flightstick Pro,
ThrustMaster FCS or 6 and 8 button gamepads. For more information on
how to use the driver please read Documentation/joystick.txt
FPGaming and MadCatz A3D controllers
CONFIG_JOY_ASSASIN
......@@ -8506,25 +8507,26 @@ CONFIG_JOY_ASSASIN
MadCatz Panther XL. For more information on how to use the driver
please read Documentation/joystick.txt
Gravis GrIP gamepads
Gravis GrIP joysticks and gamepads
CONFIG_JOY_GRAVIS
Say Y here if you have a Gravis GamePad Pro. For more information
on how to use the driver please read Documentation/joystick.txt
Say Y here if you have a Gravis GamePad Pro, Gravis Xterminator or
Gravis Blackhawk Digital. For more information on how to use the
driver please read Documentation/joystick.txt
PDPI Lightning L4 gamecards
PDPI Lightning 4 gamecards
CONFIG_JOY_LIGHTNING
Say Y here if you have a PDPI Lightning L4 gamecard and an analog
Say Y here if you have a PDPI Lightning 4 gamecard and an analog
joystick or gamepad connected to it. For more information on how to
use the driver please read Documentation/joystick.txt
Logitech Digital joysticks
Logitech Digital joysticks and gamepads
CONFIG_JOY_LOGITECH
Say Y here if you have a Logitech WingMan Extreme Digital,
Logitech ThunderPad Digital or Logitech CyberMan 2. For more
information on how to use the driver please read
Documentation/joystick.txt
Microsoft SideWinder, Genius Digital joysticks
Microsoft SideWinder, Genius Digital joysticks and gamepads
CONFIG_JOY_SIDEWINDER
Say Y here if you have a Microsoft SideWinder 3d Pro, Microsoft
SideWinder Precision Pro, Microsoft SideWinder Force Feedback Pro,
......@@ -8532,34 +8534,35 @@ CONFIG_JOY_SIDEWINDER
more information on how to use the driver please read
Documentation/joystick.txt
ThrustMaster DirectConnect (BSP) joysticks
ThrustMaster DirectConnect joysticks and gamepads
CONFIG_JOY_THRUSTMASTER
Say Y here if you have a ThrustMaster Millenium 3D Inceptor,
ThrustMaster 3D Rage Pad, or ThrustMaster WCS III. For more
information on how to use the driver please read
Documentation/joystick.txt
Say Y here if you have a ThrustMaster Millenium 3D Inceptor or a
ThrustMaster 3D Rage Pad. For more information on how to use the
driver please read Documentation/joystick.txt
NES, SNES, PSX, Multisystem gamepads
NES, SNES, PSX, Multisystem joysticks and gamepads
CONFIG_JOY_CONSOLE
Say Y here if you have a Nintendo Entertainment System gamepad,
Super Nintendo Entertainment System gamepad, Sony PlayStation
gamepad or a Multisystem -- Atari, Amiga, Commodore, Amstrad CPC
joystick. For more information on how to use the driver please read
Documentation/joystick.txt
Documentation/joystick.txt and Documentation/joystick-parport.txt
Sega, Multisystem gamepads
Sega, Multisystem joysticks and gamepads
CONFIG_JOY_DB9
Say Y here if you have a Sega Master System gamepad, Sega Genesis
gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
Commodore, Amstrad CPC joystick. For more information on how to use
the driver please read Documentation/joystick.txt
the driver please read Documentation/joystick.txt and
Documentation/joystick-parport.txt
TurboGraFX Multisystem joystick interface
CONFIG_JOY_TURBOGRAFX
Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
and want to use it with Multiststem -- Atari, Amiga, Commodore,
Amstrad CPC joystick. For more information on how to use the driver
please read Documentation/joystick-parport.txt
please read Documentation/joystick-parport.txt and
Documentation/joystick-parport.txt
Amiga joysticks
CONFIG_JOY_AMIGA
......
......@@ -506,14 +506,14 @@ more joysticks/pads.
~~~~~~~~~~~~~~~~~~~~
The joy-turbografx.c driver uses a very simple kernel/module command line:
js_tg=port,count
js_tg=port,js1,js2,js3,js4,js5,js6,js7
Where 'port' is either the address of the parallel port the interface is
connected to (eg. 0x378), or, if you are using the parport driver of 2.1+
Linux kernels, the number of the parport interface (eg. 0 for parport0).
'Count' is the number of Multisystem, 1-button joysticks connected to the
interface.
'jsX' is the number of buttons the Multisystem joysticks connected to the
interface ports 1-7 have. For a standard multisystem joystick, this is 1.
Should you want to use more than one of these interfaces at once, you can
use js_tg_2 and js_tg_3 as additional command line parameters for two more
......
Linux Joystick driver v1.2.12
Linux Joystick driver v1.2.13
(c) 1996-1998 Vojtech Pavlik <vojtech@ucw.cz>
----------------------------------------------------------------------------
......@@ -30,10 +30,11 @@ in the package: See the file COPYING.
The joystick driver for Linux provides support for a variety of joysticks
and similar devices.
These currently include various analog joysticks (both variable resistor
based and microswitch+resistor based), following IBM PC joystick standard,
with extensions like additional hats and buttons compatible with CH
Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads.
These currently include various analog joysticks and gamepads (both
variable resistor based and microswitch+resistor based), following IBM PC
joystick standard, with extensions like additional hats and buttons
compatible with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button
gamepads.
In addition to these it also supports some of the new PC joysticks that
use proprietary digital protocols to communicate over the gameport,
......@@ -54,13 +55,23 @@ Amiga linux port.
this driver can't make complete use of, I'm very interested in hearing about
them. Bug reports and success stories are also welcome.
The joystick package is available at the following FTP site:
The joystick package is available at the following FTP sites:
ftp://atrey.karlin.mff.cuni.cz/pub/linux/joystick/joystick-1.2.x.tar.gz
ftp://atrey.karlin.mff.cuni.cz/pub/linux/joystick/
ftp://artax.karlin.mff.cuni.cz/pub/linux/joystick/
The joystick driver is also included in the Linux 2.1 kernels:
ftp://linux.kernel.org/pub/linux/kernel/v2.1/
And a homepage of the driver is at:
http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/
http://artax.karlin.mff.cuni.cz/~vojtech/joystick/
A mirror of the homepage is at:
http://www.trylinux.com/projects/joystick/
There is also a mailing list for the driver at:
......@@ -70,27 +81,42 @@ send "subscribe linux-joystick Your Name" to subscribe to it.
2. Usage
~~~~~~~~
To use the driver as a standalone module, without patching the kernel, you
first need to edit the Makefile to meet your needs (namely whether you use
MODVERSIONS). Then you compile the driver by typing
You could have obtained this driver in two different ways - either in the
joystick package or in the kernel. Because, for successful usage of the
joysticks, the utilities in the package are useful, maybe necessary, and
definitely recommended, I suggest you getting the package at some of the
above mentioned locations. The rest of this file assumes you have it.
2.1 Compiling the driver package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To compile the utilities in the joystick package, and the driver itself,
as a standalone module, you first unpack the package, and then edit the
Makefile to meet your needs (namely whether are you using versioned
modules). Then you compile it
make
And after compiling you first
And after that you install it
insmod joystick.o
make install
and then
In case you have not used the driver before, you'll need to create the
joystick device files in /dev so that applications can use them:
insmod joy-something.o
make devs
where 'something' is the type of your joystick. See below for more precise
explanation. Of course, you can insmod more than one hardware specific
module at once, if you have more than one joystick installed.
For manual creation of the joystick devices, check the
Documentation/devices.txt file in the Linux source tree.
Should you not want to mess with the kernel, and just use the driver
standalone, as modules, skip the next two sections, proceeding right to 2.4,
because all you need is already done.
If you want to have the driver compiled into your kernel, you first need
to patch the kernel, so that it contains the current driver version. You do
that with a command:
2.2 Patching the kernel
~~~~~~~~~~~~~~~~~~~~~~~
If you already have the most recent joystick driver in your kernel, skip
this section. If not, you need to patch the kernel, so that it contains the
current driver version. You do that with a command:
patch -Esp1 < /usr/src/joystick-1.2.x/kernel-2.x.y.diff
......@@ -98,29 +124,101 @@ in
/usr/src/linux
2.3 Compiling the kernel
~~~~~~~~~~~~~~~~~~~~~~~~
To compile joystick support into the kernel, use the kernel configuration
scripts, and answer 'Y' to Joystick support and also to at least one of the
hardware specific options.
hardware specific options. After doing something like
make bzlilo
you are done with the driver installation. Just reboot and the driver
should find all the connected joysticks. Read the notes about the hardware
specific drivers later in this file, though.
You can also compile the driver as modules, answering 'M' to all joystick
support you want to have modules for. It is possible to have the main
joystick driver compiled into the kernel and the hardware dependent drivers
as modules.
as modules. After you compile the modules
After you're done with installation of the driver itself, you'll need to
create the joystick device files in /dev so that applications can use them.
This is done by typing
make modules
make devs
And install them
make modules_install
you're set, and can proceed to the next step.
2.4 Inserting the modules into the kernel
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After installing the modules you'll first need to insert the generic
joystick driver module into the kernel
insmod joystick
and then one or more of the hardware specific modules
insmod joy-something
where 'something' is the type of your joystick. See below for more precise
explanation.
in the joystick driver's directory. For manual creation of the joystick
devices, check the Documentation/devices.txt file in the Linux source tree.
2.5 Verifying that it works
~~~~~~~~~~~~~~~~~~~~~~~~~~~
For testing the joystick driver functionality, there is the jstest
program. You run it by typing:
2.1 Analog joysticks
jstest /dev/js0
And it should show a line with the joystick values, which update as you
move the stick, and press its buttons. The axes should all be zero when the
joystick is in the center position. They should not jitter by themselves to
other close values, and they also should be steady in any other position of
the stick. They should have the full range from -32767 to 32767. If all this
is met, then it's all fine, and you can play the games. :)
If it's not, then there might be a problem. Try to calibrate the joystick,
and if it still doesn't work, read the drivers section of this file, the
troubleshooting section, and the FAQ.
2.6. Calibration
~~~~~~~~~~~~~~~~
For most joysticks you won't need any manual calibration, since the
joystick should be autocalibrated by the driver automagically. However, with
some analog joysticks, that either do not use linear resistors, or if you
want better precision, you can use the jscal program
jscal -c /dev/js0
included in the joystick package to set better correction coefficients than
what the driver would choose itself.
After calibrating the joystick you can verify if you like the new
calibration using the jstest command, and if you do, you then can save the
correction coefficients into a file
jscal -s /dev/js0 > /etc/joystick.cal
And add a line to your rc script executing that file
source /etc/joystick.cal
This way, after the next reboot your joystick will remain calibrated. You
can also add the jscal -s line to your shutdown script.
3. HW specific driver information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this section each of the separate hardware specific drivers is described.
3.1 Analog joysticks
~~~~~~~~~~~~~~~~~~~~
The joy-analog.c uses the standard analog inputs of the gameport, and
thus supports all standard joysticks. However the only types that can be
autodetected are:
The joy-analog.c uses the standard analog inputs of the gameport, and thus
supports all standard joysticks and gamepads. It also supports extensions
like additional hats and buttons compatible with CH Flightstick Pro,
ThrustMaster FCS or 6 and 8 button gamepads.
However the only types that can be autodetected are:
* 2-axis, 4-button joystick
* 3-axis, 4-button joystick
......@@ -204,7 +302,7 @@ Using this method you'd get a command line:
And it would do the same as the above explained command line. Use
whichever way you like best.
2.2 Microsoft SideWinder and Genius Digital joysticks
3.2 Microsoft SideWinder and Genius Digital joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SideWinder and Genius Digital joysticks are supported by the
joy-sidewinder.c module. All currently supported joysticks:
......@@ -221,7 +319,7 @@ joy-sidewinder.c module. All currently supported joysticks:
by the analog driver described above. SideWinder FreeStyle Pro and
SideWinder Force Feedback Wheel are not supported yet.
2.3 Logitech Digital joysticks
3.3 Logitech Digital joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Logitech Digital joysticks are supported by the joy-logitech.c module. It
currently supports these devices:
......@@ -239,24 +337,25 @@ serial port and is not supported yet. Logitech Wingman Force, Wingman
Formula, Wingman Formula Force, Wingman Gamepad, Wingman Interceptor are USB
joysticks, with optional serial port connection, and are not supported yet.
2.4 Gravis GrIP
3.4 Gravis GrIP
~~~~~~~~~~~~~~~
Gravis GrIP gamepads are supported by the joy-gravis.c module. It
currently supports only:
currently supports:
* Gravis GamePad Pro
* Gravis Xterminator
* Gravis Blackhawk Digital
Both the pads are be autodetected, and you can even use any combination of
up to two these pads either chained together or using an Y-cable on a single
All these pads are autodetected, and you can even use any combination of
up to two of these pads either chained together or using an Y-cable on a single
gameport.
Gravis Blackhawk Digital, and GrIP MultiPort pads are not supported yet.
GrIP MultiPort support is in the works. Gravis Xcalibur, ArcadeXtreme,
GamePad Pro/M are joysticks/pads that probably never reached mass
production.
production. Gravis Stinger is a serial device and hopefully will be
supported in the future.
2.5 FPGaming A3D and MadCatz A3D
3.5 FPGaming A3D and MadCatz A3D
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Assasin 3D protocol created by FPGaming, is used both by FPGaming
themselves and is licensed to MadCatz. A3D devices are supported by the
......@@ -274,22 +373,22 @@ which has the same syntax as js_an for the analog driver.
The trackball support is far from perfect at this stage of development,
but should be well usable.
2.6 ThrustMaster DirectConnect (BSP)
3.6 ThrustMaster DirectConnect (BSP)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The TM DirectConnect (BSP) protocol is supported by the joy-thrustmaster.c
module. It currently supports:
* ThrustMaster Millenium 3D Inceptor
* ThrustMaster 3D Rage Pad
* ThrustMaster Weapon Control System III
All these drvices are autodetected, and thus no parameters to the module
Both these drvices are autodetected, and thus no parameters to the module
are needed.
The only tested device was the Millenium. Rage Pad might work, and
WCS III won't, because important parts of code for that are missing.
The Millenium and Rage Pad should work fine now. TM WCS III won't work,
because important parts of code for that are missing. I'm not sure if it was
ever mass produced.
2.7 PDPI Lightning 4 gamecards
3.7 PDPI Lightning 4 gamecards
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PDPI Lightning 4 gamecards are supported by the joy-lightning.c module.
This driver is only for analog joysticks connected to the card - if you want
......@@ -321,7 +420,7 @@ port the joystick is attached to:
See the description of analog joystick driver for explanations of m0 and
n0 values.
2.8 Amiga
3.8 Amiga
~~~~~~~~~
Amiga joysticks, connected to an Amiga, are supported by the joy-amiga.c
driver. Since they can't be autodetected, the driver has a command line.
......@@ -339,11 +438,11 @@ the Amiga.
No more joystick types are supported now, but that should change in the
future if I get an Amiga in the reach of my fingers.
2.9 Game console and 8-bit pads and joysticks
3.9 Game console and 8-bit pads and joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See joystick-parport.txt for more info.
3. Troubleshooting
4. Troubleshooting
~~~~~~~~~~~~~~~~~~
There is quite a high probability that you run into some problems. For
testing whether the driver works, if in doubt, use the jstest utility in
......@@ -359,7 +458,8 @@ please use the joydump utility first. It's created just by typing
make joydump.o
in the driver's directory. It is run then by typing
in the directory where you unpacked the joystick package. It is run then
by typing
insmod joydump.o
......@@ -370,7 +470,7 @@ with your problem report.
Oh, and read the FAQ! :)
4. FAQ
5. FAQ
~~~~~~
Q: The driver doesn't find any joysticks connected to my soundcard with the
message "joy-something: no joysticks found" and "joy-something.o:
......@@ -420,14 +520,9 @@ PC?
A: Yes, it is possible, but it'll burn your serial port or the pad. It
won't work, of course.
5. Calibration
~~~~~~~~~~~~~~
For most joysticks you won't need any manual calibration, since the
joystick should be autocalibrated by the driver automagically. However, with
some analog joysticks, that either do not use linear resistors, or if you
want better precision, you can use the jscal program included in the
joystick package to set better correction coefficients than what the driver
would choose itself.
Q: My joystick doesnt work with Quake / Quake 2. What's the cause?
A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses
for them.
6. Programming Interface
~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -449,27 +544,27 @@ the driver provides up to 32.
Thanks to the following people who contributed code, ideas or specifications
to the joystick driver development:
0.1-0.5 Arthur C. Smith <asmith@cbnewsd.att.com>
0.5 Eyal Lebedinsky <eyal@eyal.emu.id.au>
0.6 Jeff Tranter <tranter@software.mitel.com>
0.7 Carlos Puchol <cpg@cs.utexas.edu>
0.7.1-0.8 Matt Rhoten <mrhoten@oz.net>
0.7.3 Dan Fandrich <dan@fch.wimsey.bc.ca>
0.7.3 Sverker Wilberg <sverkerw@manila.docs.uu.se>
0.8 Hal Maney <maney@norden.com>
0.8 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
0.9 Alan Cox <alan@lxorguk.ukuu.org.uk>
1.1.0 John Markus Bjorndalen <johnm@cs.uit.no>
1.1.0 Boris Muehmer <mhs@cybernet-ag.de>
1.1.0 Robert W. Grubbs <rwgrubbs@vt.edu>
1.1.0 Pete Chown <pete.chown@skygate.co.uk>
1.1.0 Benji York <benji@cookeville.com>
1.1.3 Leslie F. Donaldson <donaldlf@cs.rose-hulman.edu>
1.2.0 Eng-Jon Ong <ongej@dcs.qmw.ac.uk>
1.2.8 Ragnar Hojland Espinosa <ragnar@lightside.ddns.org>
1.1.0-1.2.9 Brian Gerst <bgerst@quark.vpplus.com>
1.2.3-1.2.12 Andree Borrmann <a.borrmann@tu-bs.de>
0.9.0-1.2.12 Vojtech Pavlik <vojtech@ucw.cz>
Arthur C. Smith <asmith@cbnewsd.att.com>
Eyal Lebedinsky <eyal@eyal.emu.id.au>
Jeff Tranter <tranter@software.mitel.com>
Carlos Puchol <cpg@cs.utexas.edu>
Matt Rhoten <mrhoten@oz.net>
Dan Fandrich <dan@fch.wimsey.bc.ca>
Sverker Wilberg <sverkerw@manila.docs.uu.se>
Hal Maney <maney@norden.com>
Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
Alan Cox <alan@lxorguk.ukuu.org.uk>
John Markus Bjorndalen <johnm@cs.uit.no>
Boris Muehmer <mhs@cybernet-ag.de>
Robert W. Grubbs <rwgrubbs@vt.edu>
Pete Chown <pete.chown@skygate.co.uk>
Benji York <benji@cookeville.com>
Leslie F. Donaldson <donaldlf@cs.rose-hulman.edu>
Eng-Jon Ong <ongej@dcs.qmw.ac.uk>
Ragnar Hojland Espinosa <ragnar@lightside.ddns.org>
Brian Gerst <bgerst@quark.vpplus.com>
Andree Borrmann <a.borrmann@tu-bs.de>
Martin Giguere <zefrench@hotmail.com>
If you think you should be in this list and are not, it's possible that
I forgot to include you - contact me and I'll correct the error. :)
......@@ -506,14 +601,7 @@ about their hardware .... :(
9. To do
~~~~~~~~
Sooner or later I'll do these:
Fix possible races at open/close
Fix possible read/timer races
Make the driver SMP-friendly
Support joysticks on Linux/m68k/Atari
Support joysticks on Linux/FM-TOWNS (?)
Support even more joystick types
See the TODO file for the list of things planned.
10. Current driver status
~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -545,6 +633,7 @@ joy-db9.c: Multi1 stick - OK
Sega Saturn pad - unknown
joy-gravis.c Gravis GamePad Pro - OK
Gravis Xterminator - OK
Gravis Blackhawk Digital- OK
joy-lightning.c PDPI Lightning 4 - OK
joy-logitech.c WingMan Extreme Digital - OK
CyberMan 2 - OK
......@@ -555,8 +644,7 @@ joy-sidewinder.c SW 3D Pro - OK
SW PP - OK
SW FFP - OK
joy-thrustmaster.c Millenium 3D Inceptor - OK
3D-Rage pad - unknown
WCS III - incomplete
3D-Rage Pad - OK
joy-turbografx.c Multi1 stick - OK
Please help me and send me success / failure reports for the drivers,
......
......@@ -2,16 +2,16 @@
# Joystick lowlevel driver configuration
#
dep_tristate ' Classic PC analog joysticks' CONFIG_JOY_ANALOG $CONFIG_JOYSTICK
dep_tristate ' Classic PC analog joysticks and gamepads' CONFIG_JOY_ANALOG $CONFIG_JOYSTICK
dep_tristate ' FPGaming and MadCatz A3D controllers' CONFIG_JOY_ASSASIN $CONFIG_JOYSTICK
dep_tristate ' Gravis GrIP gamepads' CONFIG_JOY_GRAVIS $CONFIG_JOYSTICK
dep_tristate ' Logitech Digital joysticks' CONFIG_JOY_LOGITECH $CONFIG_JOYSTICK
dep_tristate ' Microsoft SideWinder, Genius Digital joysticks' CONFIG_JOY_SIDEWINDER $CONFIG_JOYSTICK
dep_tristate ' ThrustMaster DirectConnect (BSP) joysticks' CONFIG_JOY_THRUSTMASTER $CONFIG_JOYSTICK
dep_tristate ' PDPI Lightning L4 gamecards' CONFIG_JOY_LIGHTNING $CONFIG_JOYSTICK
dep_tristate ' Gravis GrIP joysticks and gamepads' CONFIG_JOY_GRAVIS $CONFIG_JOYSTICK
dep_tristate ' Logitech Digital joysticks and gamepads' CONFIG_JOY_LOGITECH $CONFIG_JOYSTICK
dep_tristate ' Microsoft SideWinder, Genius Digital joysticks and gamepads' CONFIG_JOY_SIDEWINDER $CONFIG_JOYSTICK
dep_tristate ' ThrustMaster DirectConnect joysticks and gamepads' CONFIG_JOY_THRUSTMASTER $CONFIG_JOYSTICK
dep_tristate ' PDPI Lightning 4 gamecards' CONFIG_JOY_LIGHTNING $CONFIG_JOYSTICK
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate ' NES, SNES, PSX, Multisystem gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK
dep_tristate ' Sega, Multisystem gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK
dep_tristate ' NES, SNES, PSX, Multisystem joysticks and gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK
dep_tristate ' Sega, Multisystem joysticks and gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK
dep_tristate ' TurboGraFX Multisystem joystick interface' CONFIG_JOY_TURBOGRAFX $CONFIG_JOYSTICK
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
......
......@@ -148,8 +148,8 @@ int __init js_am_init(void)
#ifdef MODULE
void cleanup_module(void)
{
while (js_am_port) {
if (js_am_port->devs[0])
while (js_am_port != NULL) {
if (js_am_port->devs[0] != NULL)
js_unregister_device(js_am_port->devs[0]);
js_am_port = js_unregister_port(js_am_port);
}
......
......@@ -195,9 +195,9 @@ void cleanup_module(void)
int i;
struct js_an_info *info;
while (js_an_port) {
while (js_an_port != NULL) {
for (i = 0; i < js_an_port->ndevs; i++)
if (js_an_port->devs[i])
if (js_an_port->devs[i] != NULL)
js_unregister_device(js_an_port->devs[i]);
info = js_an_port->info;
release_region(info->io, 1);
......
......@@ -410,9 +410,9 @@ void cleanup_module(void)
int i;
struct js_as_info *info;
while (js_as_port) {
while (js_as_port != NULL) {
for (i = 0; i < js_as_port->ndevs; i++)
if (js_as_port->devs[i])
if (js_as_port->devs[i] != NULL)
js_unregister_device(js_as_port->devs[i]);
info = js_as_port->info;
release_region(info->io, 1);
......
......@@ -373,9 +373,9 @@ void cleanup_module(void)
struct js_console_info *info;
int i;
while (js_console_port) {
while (js_console_port != NULL) {
for (i = 0; i < js_console_port->ndevs; i++)
if (js_console_port->devs[i])
if (js_console_port->devs[i] != NULL)
js_unregister_device(js_console_port->devs[i]);
info = js_console_port->info;
#ifdef USE_PARPORT
......@@ -428,11 +428,11 @@ static struct js_port __init *js_console_probe(int *config, struct js_port *port
struct parport *pp;
if (config[0] > 0x10)
for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
else
for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
if (!pp) {
if (pp == NULL) {
printk(KERN_ERR "joy-console: no such parport\n");
return port;
}
......
......@@ -38,8 +38,8 @@
MODULE_AUTHOR("Andree Borrmann <A.Borrmann@tu-bs.de>");
MODULE_PARM(js_db9, "2i");
MODULE_PARM(js_db9_2, "0-2i");
MODULE_PARM(js_db9_3, "0-2i");
MODULE_PARM(js_db9_2, "2i");
MODULE_PARM(js_db9_3, "2i");
#define JS_MULTI_STICK 0x01
#define JS_MULTI2_STICK 0x02
......@@ -227,42 +227,6 @@ static int js_db9_read(void *xinfo, int **axes, int **buttons)
return 0;
}
/*
* js_db9_enable_ps2() enables PS/2 capabilities on a parallel port and
* switches data lines to input mode. We should use parport_change_mode() for
* that if parport present - unfortunately that does nothing and only contains
* a FIXME comment.
*/
static inline void js_db9_enable_ps2(struct js_db9_info *info)
{
#ifdef USE_PARPORT
int io = info->port->port->base;
#else
int io = info->port;
#endif
outb(0x35,io+0x402); /* enable PS/2 mode: */
outb(JS_DB9_NORMAL,io+2); /* reverse direction, enable Select signal: */
}
/*
* js_db9_disable_ps2() disables PS/2 capabilities on a parallel port
* and restores it to standard mode.
*/
static inline void js_db9_disable_ps2(struct js_db9_info *info)
{
#ifdef USE_PARPORT
int io = info->port->port->base;
#else
int io = info->port;
#endif
outb(0,io+2); /* normal direction */
outb(0x15,io+0x402); /* enable normal mode */
}
/*
* open callback: claim parport.
*/
......@@ -275,7 +239,9 @@ int js_db9_open(struct js_dev *dev)
#ifdef USE_PARPORT
if (parport_claim(info->port)) return -EBUSY;
#endif
js_db9_enable_ps2(info);
JS_PAR_ECTRL_OUT(0x35,info->port); /* enable PS/2 mode: */
JS_PAR_CTRL_OUT(JS_DB9_NORMAL,info->port); /* reverse direction, enable Select signal */
}
MOD_INC_USE_COUNT;
......@@ -293,7 +259,10 @@ int js_db9_close(struct js_dev *dev)
MOD_DEC_USE_COUNT;
if (!MOD_IN_USE) {
js_db9_disable_ps2(info);
JS_PAR_CTRL_OUT(0x00,info->port); /* normal direction */
JS_PAR_ECTRL_OUT(0x15,info->port); /* enable normal mode */
#ifdef USE_PARPORT
parport_release(info->port);
#endif
......@@ -306,7 +275,7 @@ void cleanup_module(void)
{
struct js_db9_info *info;
while (js_db9_port) {
while (js_db9_port != NULL) {
js_unregister_device(js_db9_port->devs[0]);
info = js_db9_port->info;
#ifdef USE_PARPORT
......@@ -359,11 +328,11 @@ static struct js_port __init *js_db9_probe(int *config, struct js_port *port)
struct parport *pp;
if (config[0] > 0x10)
for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
else
for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
if (!pp) {
if (pp == NULL) {
printk(KERN_ERR "joy-db9: no such parport\n");
return port;
}
......
......@@ -43,6 +43,7 @@
#define JS_GR_STROBE_GPP 75
#define JS_GR_MODE_XT 2
#define JS_GR_MODE_BD 3
#define JS_GR_LENGTH_XT 4
#define JS_GR_STROBE_XT 30
#define JS_GR_MAX_CHUNKS_XT 10
......@@ -189,9 +190,10 @@ static int js_gr_read(void *xinfo, int **axes, int **buttons)
axes[i][0] = (data[0] >> 2) & 0x3f;
axes[i][1] = 63 - ((data[0] >> 8) & 0x3f);
axes[i][2] = (data[1] >> 2) & 0x3f;
axes[i][3] = (data[1] >> 8) & 0x3f;
axes[i][4] = (data[2] >> 8) & 0x3f;
axes[i][2] = (data[1] >> 2) & 0x3f;
axes[i][3] = (data[1] >> 8) & 0x3f;
axes[i][4] = (data[2] >> 8) & 0x3f;
axes[i][5] = ((data[2] >> 1) & 1) - ( data[2] & 1);
axes[i][6] = ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1);
axes[i][7] = ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1);
......@@ -201,6 +203,22 @@ static int js_gr_read(void *xinfo, int **axes, int **buttons)
break;
case JS_GR_MODE_BD:
if (js_gr_xt_read_packet(info->io, (i << 1) + 4, data)) return -1;
axes[i][0] = (data[0] >> 2) & 0x3f;
axes[i][1] = 63 - ((data[0] >> 8) & 0x3f);
axes[i][2] = (data[2] >> 8) & 0x3f;
axes[i][3] = ((data[2] >> 1) & 1) - ( data[2] & 1);
axes[i][4] = ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1);
buttons[i][0] = ((data[3] >> 6) & 0x01) | ((data[3] >> 3) & 0x06)
| ((data[3] >> 4) & 0x18);
break;
default:
break;
......@@ -276,6 +294,28 @@ static void __init js_gr_init_corr(int mode, struct js_corr *corr)
break;
case JS_GR_MODE_BD:
for (i = 0; i < 3; i++) {
corr[i].type = JS_CORR_BROKEN;
corr[i].prec = 0;
corr[i].coef[0] = 31 - 4;
corr[i].coef[1] = 32 + 4;
corr[i].coef[2] = (1 << 29) / (32 - 14);
corr[i].coef[3] = (1 << 29) / (32 - 14);
}
for (i = 3; i < 5; i++) {
corr[i].type = JS_CORR_BROKEN;
corr[i].prec = 0;
corr[i].coef[0] = 0;
corr[i].coef[1] = 0;
corr[i].coef[2] = (1 << 29);
corr[i].coef[3] = (1 << 29);
}
break;
}
}
......@@ -286,9 +326,9 @@ static void __init js_gr_init_corr(int mode, struct js_corr *corr)
static struct js_port __init *js_gr_probe(int io, struct js_port *port)
{
struct js_gr_info info;
char *names[] = { NULL, "Gravis GamePad Pro", "Gravis Xterminator" };
char axes[] = { 0, 2, 9 };
char buttons[] = { 0, 10, 11 };
char *names[] = { NULL, "Gravis GamePad Pro", "Gravis Xterminator", "Gravis Blackhawk Digital"};
char axes[] = { 0, 2, 9, 5};
char buttons[] = { 0, 10, 11, 5};
unsigned int data[JS_GR_LENGTH_XT];
int i;
......@@ -298,7 +338,12 @@ static struct js_port __init *js_gr_probe(int io, struct js_port *port)
for (i = 0; i < 2; i++) {
if (!js_gr_gpp_read_packet(io, (i << 1) + 4, data)) info.mode[i] = JS_GR_MODE_GPP;
if (!js_gr_xt_read_packet(io, (i << 1) + 4, data)) info.mode[i] = JS_GR_MODE_XT;
if (!js_gr_xt_read_packet(io, (i << 1) + 4, data)) {
if ((data[3] & 7) == 7)
info.mode[i] = JS_GR_MODE_XT;
if ((data[3] & 7) == 0)
info.mode[i] = JS_GR_MODE_BD;
}
}
if (!info.mode[0] && !info.mode[1]) return port;
......@@ -344,9 +389,9 @@ void cleanup_module(void)
int i;
struct js_gr_info *info;
while (js_gr_port) {
while (js_gr_port != NULL) {
for (i = 0; i < js_gr_port->ndevs; i++)
if (js_gr_port->devs[i])
if (js_gr_port->devs[i] != NULL)
js_unregister_device(js_gr_port->devs[i]);
info = js_gr_port->info;
release_region(info->io, 1);
......
......@@ -352,9 +352,9 @@ void cleanup_module(void)
int cal[4] = {59, 59, 59, 59};
struct js_l4_info *info;
while (js_l4_port) {
while (js_l4_port != NULL) {
for (i = 0; i < js_l4_port->ndevs; i++)
if (js_l4_port->devs[i])
if (js_l4_port->devs[i] != NULL)
js_unregister_device(js_l4_port->devs[i]);
info = js_l4_port->info;
js_l4_setcal(info->port, cal);
......
......@@ -361,7 +361,7 @@ void cleanup_module(void)
{
struct js_lt_info *info;
while (js_lt_port) {
while (js_lt_port != NULL) {
js_unregister_device(js_lt_port->devs[0]);
info = js_lt_port->info;
release_region(info->io, 1);
......
......@@ -88,6 +88,11 @@ static void __init js_sw_init_digital(int io)
} while (delays[i++]);
__restore_flags(flags);
for (i = 0; i < 4; i++) {
udelay(300);
outb(0xff, io);
}
return;
}
......@@ -137,19 +142,21 @@ static int js_sw_read_packet(int io, int l1, int l2, int strobe, __u64 *data)
__restore_flags(flags);
*data = 0;
t = i;
if (t == l1) {
if (i == l1) {
t = i > 64 ? 64 : i;
for (i = 0; i < t; i++)
*data |= (__u64) (buf[i] & 1) << i;
return t;
}
if (t == l2) {
if (i == l2) {
t = i > 22 ? 22 : i;
for (i = 0; i < t; i++)
*data |= (__u64) buf[i] << (3 * i);
return t * 3;
}
return t;
return i;
}
/*
......@@ -199,7 +206,7 @@ static int js_sw_read(void *xinfo, int **axes, int **buttons)
i = js_sw_read_packet(info->io, -1, 22, JS_SW_EXT_STROBE, &data);
} else {
i = js_sw_read_packet(info->io, 64, 66, JS_SW_EXT_STROBE, &data);
if (i == 192) info->optimize = 1;
if (i == 198) info->optimize = 1;
}
if (i < 60) {
......@@ -456,9 +463,9 @@ void cleanup_module(void)
int i;
struct js_sw_info *info;
while (js_sw_port) {
while (js_sw_port != NULL) {
for (i = 0; i < js_sw_port->ndevs; i++)
if (js_sw_port->devs[i])
if (js_sw_port->devs[i] != NULL)
js_unregister_device(js_sw_port->devs[i]);
info = js_sw_port->info;
release_region(info->io, 1);
......
......@@ -39,12 +39,12 @@
#include <linux/module.h>
#include <linux/string.h>
#define JS_TM_MAX_START 200
#define JS_TM_MAX_STROBE 15
#define JS_TM_MAX_START 400
#define JS_TM_MAX_STROBE 25
#define JS_TM_MAX_LENGTH 13
#define JS_TM_MODE_M3DI 1
#define JS_TM_MODE_3DRP 2
#define JS_TM_MODE_3DRP 3
#define JS_TM_MODE_WCS3 4
#define JS_TM_MODE_MAX 5 /* Last mode + 1 */
......@@ -73,7 +73,7 @@ struct js_tm_info {
unsigned char mode;
};
static int js_tm_id_to_def[JS_TM_MODE_MAX] = {0x00, 0x42, 0x22, 0x00, 0x00};
static int js_tm_id_to_def[JS_TM_MODE_MAX] = {0x00, 0x42, 0x00, 0x22, 0x00};
/*
* js_tm_read_packet() reads a ThrustMaster packet.
......@@ -120,6 +120,7 @@ static int js_tm_read_packet(int io, unsigned char *data)
i++;
}
} else { /* Start bit */
data[i] = 0;
error |= ~v & 1;
j++;
}
......@@ -251,10 +252,10 @@ static void __init js_tm_init_corr(int num_axes, int mode, int **axes, struct js
static struct js_port __init *js_tm_probe(int io, struct js_port *port)
{
struct js_tm_info info;
char *names[JS_TM_MODE_MAX] = { NULL, "ThrustMaster Millenium 3D Inceptor",
"ThrustMaster Rage 3D Gamepad", NULL, "ThrustMaster WCS III" };
char axes[JS_TM_MODE_MAX] = { 0, 6, 2, 0, 0 };
char buttons[JS_TM_MODE_MAX] = { 0, 5, 10, 0, 0 };
char *names[JS_TM_MODE_MAX] = { NULL, "ThrustMaster Millenium 3D Inceptor", NULL,
"ThrustMaster Rage 3D Gamepad", "ThrustMaster WCS III" };
char axes[JS_TM_MODE_MAX] = { 0, 6, 0, 2, 0 };
char buttons[JS_TM_MODE_MAX] = { 0, 5, 0, 10, 0 };
unsigned char data[JS_TM_MAX_LENGTH];
unsigned char u;
......@@ -320,7 +321,7 @@ void cleanup_module(void)
{
struct js_tm_info *info;
while (js_tm_port) {
while (js_tm_port != NULL) {
js_unregister_device(js_tm_port->devs[0]);
info = js_tm_port->info;
release_region(info->io, 1);
......
......@@ -42,21 +42,26 @@
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_PARM(js_tg, "2i");
MODULE_PARM(js_tg_2, "0-2i");
MODULE_PARM(js_tg_3, "0-2i");
MODULE_PARM(js_tg, "2-8i");
MODULE_PARM(js_tg_2, "2-8i");
MODULE_PARM(js_tg_3, "2-8i");
#define JS_TG_BUTTON 3
#define JS_TG_UP 4
#define JS_TG_DOWN 5
#define JS_TG_LEFT 6
#define JS_TG_RIGHT 7
#define JS_TG_BUTTON1 0x08
#define JS_TG_UP 0x10
#define JS_TG_DOWN 0x20
#define JS_TG_LEFT 0x40
#define JS_TG_RIGHT 0x80
#define JS_TG_BUTTON2 0x02
#define JS_TG_BUTTON3 0x04
#define JS_TG_BUTTON4 0x01
#define JS_TG_BUTTON5 0x08
static struct js_port* js_tg_port = NULL;
static int js_tg[] __initdata = { -1, 0 };
static int js_tg_2[] __initdata = { -1, 0 };
static int js_tg_3[] __initdata = { -1, 0 };
static int js_tg[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
static int js_tg_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
static int js_tg_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
struct js_tg_info {
#ifdef USE_PARPORT
......@@ -64,7 +69,7 @@ struct js_tg_info {
#else
int port; /* hw port */
#endif
int count; /* number of joysticks */
int sticks; /* joysticks connected */
};
/*
......@@ -74,17 +79,21 @@ struct js_tg_info {
static int js_tg_read(void *xinfo, int **axes, int **buttons)
{
struct js_tg_info *info = xinfo;
int data, i;
int data1, data2, i;
for (i = 0; i < info->count; i++) {
for (i = 0; i < 7; i++)
if ((info->sticks >> i) & 1) {
JS_PAR_DATA_OUT(~(1 << i), info->port);
data = JS_PAR_STATUS(info->port) ^ ~JS_PAR_STATUS_INVERT;
data1 = JS_PAR_STATUS(info->port) ^ ~JS_PAR_STATUS_INVERT;
data2 = JS_PAR_CTRL_IN(info->port) ^ JS_PAR_CTRL_INVERT;
axes[i][0] = ((data >> JS_TG_RIGHT) & 1) - ((data >> JS_TG_LEFT) & 1);
axes[i][1] = ((data >> JS_TG_DOWN ) & 1) - ((data >> JS_TG_UP ) & 1);
axes[i][0] = ((data1 & JS_TG_RIGHT) ? 1 : 0) - ((data1 & JS_TG_LEFT) ? 1 : 0);
axes[i][1] = ((data1 & JS_TG_DOWN ) ? 1 : 0) - ((data1 & JS_TG_UP ) ? 1 : 0);
buttons[i][0] = (data >> JS_TG_BUTTON) & 1;
buttons[i][0] = ((data1 & JS_TG_BUTTON1) ? 0x01 : 0) | ((data2 & JS_TG_BUTTON2) ? 0x02 : 0)
| ((data2 & JS_TG_BUTTON3) ? 0x04 : 0) | ((data2 & JS_TG_BUTTON4) ? 0x08 : 0)
| ((data2 & JS_TG_BUTTON5) ? 0x10 : 0);
}
......@@ -97,10 +106,14 @@ static int js_tg_read(void *xinfo, int **axes, int **buttons)
int js_tg_open(struct js_dev *dev)
{
#ifdef USE_PARPORT
struct js_tg_info *info = dev->port->info;
if (!MOD_IN_USE && parport_claim(info->port)) return -EBUSY;
if (!MOD_IN_USE) {
#ifdef USE_PARPORT
if (parport_claim(info->port)) return -EBUSY;
#endif
JS_PAR_CTRL_OUT(0x04, info->port);
}
MOD_INC_USE_COUNT;
return 0;
}
......@@ -111,13 +124,15 @@ int js_tg_open(struct js_dev *dev)
int js_tg_close(struct js_dev *dev)
{
#ifdef USE_PARPORT
struct js_tg_info *info = dev->port->info;
#endif
MOD_DEC_USE_COUNT;
if (!MOD_IN_USE) {
JS_PAR_CTRL_OUT(0x00, info->port);
#ifdef USE_PARPORT
if (!MOD_IN_USE) parport_release(info->port);
parport_release(info->port);
#endif
}
return 0;
}
......@@ -127,9 +142,9 @@ void cleanup_module(void)
struct js_tg_info *info;
int i;
while (js_tg_port) {
while (js_tg_port != NULL) {
for (i = 0; i < js_tg_port->ndevs; i++)
if (js_tg_port->devs[i])
if (js_tg_port->devs[i] != NULL)
js_unregister_device(js_tg_port->devs[i]);
info = js_tg_port->info;
#ifdef USE_PARPORT
......@@ -147,19 +162,20 @@ void cleanup_module(void)
* tg gamepads.
*/
static void __init js_tg_init_corr(int count, struct js_corr **corr)
static void __init js_tg_init_corr(int sticks, struct js_corr **corr)
{
int i, j;
for (i = 0; i < count; i++)
for (j = 0; j < 2; j++) {
corr[i][j].type = JS_CORR_BROKEN;
corr[i][j].prec = 0;
corr[i][j].coef[0] = 0;
corr[i][j].coef[1] = 0;
corr[i][j].coef[2] = (1 << 29);
corr[i][j].coef[3] = (1 << 29);
}
for (i = 0; i < 7; i++)
if ((sticks >> i) & 1)
for (j = 0; j < 2; j++) {
corr[i][j].type = JS_CORR_BROKEN;
corr[i][j].prec = 0;
corr[i][j].coef[0] = 0;
corr[i][j].coef[1] = 0;
corr[i][j].coef[2] = (1 << 29);
corr[i][j].coef[3] = (1 << 29);
}
}
/*
......@@ -168,53 +184,65 @@ static void __init js_tg_init_corr(int count, struct js_corr **corr)
static struct js_port __init *js_tg_probe(int *config, struct js_port *port)
{
struct js_tg_info info;
struct js_tg_info iniinfo;
struct js_tg_info *info = &iniinfo;
int i;
if (config[0] < 0) return port;
if (config[1] < 1 || config[1] > 8) return port;
#ifdef USE_PARPORT
{
struct parport *pp;
if (config[0] > 0x10)
for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
else
for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
if (!pp) {
if (pp == NULL) {
printk(KERN_ERR "joy-tg: no such parport\n");
return port;
}
info.port = parport_register_device(pp, "joystick (turbografx)", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
if (!info.port)
info->port = parport_register_device(pp, "joystick (turbografx)", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
if (!info->port)
return port;
}
#else
info.port = config[0];
if (check_region(info.port, 3)) return port;
request_region(info.port, 3, "joystick (turbografx)");
info->port = config[0];
if (check_region(info->port, 3)) return port;
request_region(info->port, 3, "joystick (turbografx)");
#endif
info.count = config[1];
port = js_register_port(port, &info, info.count, sizeof(struct js_tg_info), js_tg_read);
port = js_register_port(port, info, 7, sizeof(struct js_tg_info), js_tg_read);
info = port->info;
info->sticks = 0;
for (i = 0; i < info.count; i++)
for (i = 0; i < 7; i++)
if (config[i+1] > 0 && config[i+1] < 6) {
#ifdef USE_PARPORT
printk(KERN_INFO "js%d: Multisystem joystick on %s\n",
js_register_device(port, i, 2, 1, "Multisystem joystick", js_tg_open, js_tg_close),
info.port->port->name);
printk(KERN_INFO "js%d: Multisystem joystick on %s\n",
js_register_device(port, i, 2, config[i+1], "Multisystem joystick", js_tg_open, js_tg_close),
info->port->port->name);
#else
printk(KERN_INFO "js%d: Multisystem joystick at %#x\n",
js_register_device(port, i, 2, 1, "Multisystem joystick", js_tg_open, js_tg_close),
info.port);
printk(KERN_INFO "js%d: Multisystem joystick at %#x\n",
js_register_device(port, i, 2, config[i+1], "Multisystem joystick", js_tg_open, js_tg_close),
info->port);
#endif
info->sticks |= (1 << i);
}
js_tg_init_corr(info.count, port->corr);
if (!info->sticks) {
#ifdef USE_PARPORT
parport_unregister_device(info->port);
#else
release_region(info->port, 3);
#endif
return port;
}
js_tg_init_corr(info->sticks, port->corr);
return port;
}
......
......@@ -32,6 +32,7 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
......@@ -456,14 +457,14 @@ static void js_do_timer(unsigned long data)
struct js_dev *curd = js_dev;
unsigned long flags;
while (curp) {
while (curp != NULL) {
curp->read(curp->info, curp->axes, curp->buttons);
curp = curp->next;
}
spin_lock_irqsave(&js_lock, flags);
while (curd) {
while (curd != NULL) {
if (data) {
js_process_data(curd);
js_sync_buff(curd);
......@@ -643,12 +644,12 @@ static int js_read(struct inode *inode, struct file *file, char *buf, int count)
if (orig_tail == jd->tail) {
new_tail = curl->tail;
curl = jd->list;
while (curl && curl->tail != jd->tail) {
while (curl != NULL && curl->tail != jd->tail) {
if (ROT(jd->bhead, new_tail, curl->tail) ||
(jd->bhead == curl->tail)) new_tail = curl->tail;
curl = curl->next;
}
if (!curl) jd->tail = new_tail;
if (curl == NULL) jd->tail = new_tail;
}
spin_unlock_irqrestore(&js_lock, flags);
......@@ -855,42 +856,51 @@ static int js_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
static int js_open(struct inode *inode, struct file *file)
{
struct js_list *curl;
struct js_list *curl, *new;
struct js_dev *jd = js_dev;
int i = MINOR(inode->i_rdev);
unsigned long flags;
int result;
int result;
if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR)
return -EINVAL;
while (i > 0 && jd) {
spin_lock_irqsave(&js_lock, flags);
while (i > 0 && jd != NULL) {
jd = jd->next;
i--;
}
if (!jd) return -ENODEV;
spin_unlock_irqrestore(&js_lock, flags);
if (jd == NULL) return -ENODEV;
if ((result = jd->open(jd))) return result;
MOD_INC_USE_COUNT;
if (!js_use_count++) js_do_timer(0);
curl = jd->list;
if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL)) != NULL) {
spin_lock_irqsave(&js_lock, flags);
spin_lock_irqsave(&js_lock, flags);
jd->list = kmalloc(sizeof(struct js_list), GFP_KERNEL);
jd->list->next = curl;
jd->list->dev = jd;
jd->list->startup = 0;
jd->list->tail = GOB(jd->bhead);
curl = jd->list;
spin_unlock_irqrestore(&js_lock, flags);
jd->list = new;
jd->list->next = curl;
jd->list->dev = jd;
jd->list->startup = 0;
jd->list->tail = GOB(jd->bhead);
file->private_data = jd->list;
file->private_data = jd->list;
spin_unlock_irqrestore(&js_lock, flags);
return 0;
} else {
result = -ENOMEM;
}
return result;
}
/*
......@@ -915,11 +925,11 @@ static void js_release(struct inode *inode, struct file *file)
while (*curp && (*curp != curl)) curp = &((*curp)->next);
*curp = (*curp)->next;
if (jd->list)
if (jd->list != NULL)
if (curl->tail == jd->tail) {
curl = jd->list;
new_tail = curl->tail;
while (curl && curl->tail != jd->tail) {
while (curl != NULL && curl->tail != jd->tail) {
if (ROT(jd->bhead, new_tail, curl->tail) ||
(jd->bhead == curl->tail)) new_tail = curl->tail;
curl = curl->next;
......@@ -957,7 +967,7 @@ static void js_dump_mem(void)
printk(",--- Dumping Devices:\n");
printk("| js_dev = %x\n", (int) js_dev);
while (curd) {
while (curd != NULL) {
printk("| %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n",
curd->next ? "|":"`",
(int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port, curd->port->io);
......@@ -967,7 +977,7 @@ static void js_dump_mem(void)
printk(">--- Dumping ports:\n");
printk("| js_port = %x\n", (int) js_port);
while (curp) {
while (curp != NULL) {
printk("| %s-port %x, next %x, io %#x, devices %d\n",
curp->next ? "|":"`",
(int) curp, (int) curp->next, curp->io, curp->ndevs);
......@@ -995,35 +1005,39 @@ struct js_port *js_register_port(struct js_port *port,
{
struct js_port **ptrp = &js_port;
struct js_port *curp;
void *all;
int i;
unsigned long flags;
spin_lock_irqsave(&js_lock, flags);
if ((all = kmalloc(sizeof(struct js_port) + 4 * devs * sizeof(void*) + infos, GFP_KERNEL)) == NULL)
return NULL;
while (*ptrp) ptrp=&((*ptrp)->next);
*ptrp = curp = kmalloc(sizeof(struct js_port), GFP_KERNEL);
curp = all;
curp->next = NULL;
curp->prev = port;
curp->read = read;
curp->ndevs = devs;
curp->devs = kmalloc(devs * sizeof(struct js_dev*), GFP_KERNEL);
for (i = 0; i < devs; i++)
curp->devs[i] = NULL;
curp->devs = all += sizeof(struct js_port);
for (i = 0; i < devs; i++) curp->devs[i] = NULL;
curp->axes = kmalloc(devs * sizeof(int*), GFP_KERNEL);
curp->buttons = kmalloc(devs * sizeof(int*), GFP_KERNEL);
curp->corr = kmalloc(devs * sizeof(struct js_corr*), GFP_KERNEL);
curp->axes = all += devs * sizeof(void*);
curp->buttons = (void*) all += devs * sizeof(void*);
curp->corr = all += devs * sizeof(void*);
if (infos) {
curp->info = kmalloc(infos, GFP_KERNEL);
curp->info = all += devs * sizeof(void*);
memcpy(curp->info, info, infos);
} else {
curp->info = NULL;
}
spin_lock_irqsave(&js_lock, flags);
while (*ptrp != NULL) ptrp=&((*ptrp)->next);
*ptrp = curp;
spin_unlock_irqrestore(&js_lock, flags);
return curp;
......@@ -1037,19 +1051,14 @@ struct js_port *js_unregister_port(struct js_port *port)
spin_lock_irqsave(&js_lock, flags);
while (*curp && (*curp != port)) curp = &((*curp)->next);
while (*curp != NULL && (*curp != port)) curp = &((*curp)->next);
*curp = (*curp)->next;
spin_unlock_irqrestore(&js_lock, flags);
prev = port->prev;
kfree(port->devs);
kfree(port->axes);
kfree(port->buttons);
kfree(port->corr);
if (port->info) kfree(port->info);
kfree(port);
spin_unlock_irqrestore(&js_lock, flags);
return prev;
}
......@@ -1058,17 +1067,16 @@ int js_register_device(struct js_port *port, int number, int axes, int buttons,
{
struct js_dev **ptrd = &js_dev;
struct js_dev *curd;
void *all;
int i = 0;
unsigned long flags;
spin_lock_irqsave(&js_lock, flags);
while (*ptrd) {
ptrd=&(*ptrd)->next;
i++;
}
if ((all = kmalloc(sizeof(struct js_dev) + 2 * axes * sizeof(int) +
2 * (((buttons - 1) >> 5) + 1) * sizeof(int) +
axes * sizeof(struct js_corr) + strlen(name) + 1, GFP_KERNEL)) == NULL)
return -1;
*ptrd = curd = kmalloc(sizeof(struct js_dev), GFP_KERNEL);
curd = all;
curd->next = NULL;
curd->list = NULL;
......@@ -1083,20 +1091,25 @@ int js_register_device(struct js_port *port, int number, int axes, int buttons,
curd->num_axes = axes;
curd->num_buttons = buttons;
curd->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
strcpy(curd->name, name);
curd->cur.axes = all += sizeof(struct js_dev);
curd->cur.buttons = all += axes * sizeof(int);
curd->new.axes = all += (((buttons - 1) >> 5) + 1) * sizeof(int);
curd->new.buttons = all += axes * sizeof(int);
curd->corr = all += (((buttons -1 ) >> 5) + 1) * sizeof(int);
curd->cur.axes = kmalloc(axes * sizeof(int), GFP_KERNEL);
curd->cur.buttons = kmalloc((((buttons - 1) >> 5) + 1) * sizeof(int), GFP_KERNEL);
curd->new.axes = kmalloc(axes * sizeof(int), GFP_KERNEL);
curd->new.buttons = kmalloc((((buttons -1 ) >> 5) + 1) * sizeof(int), GFP_KERNEL);
curd->corr = kmalloc(axes * sizeof(struct js_corr), GFP_KERNEL);
curd->name = all += axes * sizeof(struct js_corr);
strcpy(curd->name, name);
port->devs[number] = curd;
port->axes[number] = curd->new.axes;
port->buttons[number] = curd->new.buttons;
port->corr[number] = curd->corr;
spin_lock_irqsave(&js_lock, flags);
while (*ptrd != NULL) { ptrd=&(*ptrd)->next; i++; }
*ptrd = curd;
spin_unlock_irqrestore(&js_lock, flags);
return i;
......@@ -1109,17 +1122,11 @@ void js_unregister_device(struct js_dev *dev)
spin_lock_irqsave(&js_lock, flags);
while (*curd && (*curd != dev)) curd = &((*curd)->next);
while (*curd != NULL && (*curd != dev)) curd = &((*curd)->next);
*curd = (*curd)->next;
spin_unlock_irqrestore(&js_lock, flags);
kfree(dev->cur.axes);
kfree(dev->new.axes);
kfree(dev->cur.buttons);
kfree(dev->new.buttons);
kfree(dev->corr);
kfree(dev->name);
kfree(dev);
}
......
......@@ -374,13 +374,11 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
/*
* Make sure the directory is empty and the dentry isn't busy.
*/
if (dentry->d_count > 1)
shrink_dcache_parent(dentry);
retval = -ENOTEMPTY;
if (!empty_dir(bh,AFFS_I2HSIZE(inode)))
goto rmdir_done;
retval = -EBUSY;
if (dentry->d_count > 1)
if (!list_empty(&dentry->d_hash))
goto rmdir_done;
if ((retval = affs_remove_header(bh,inode)) < 0)
......
......@@ -520,7 +520,7 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
struct coda_inode_info *dircnp;
const char *name = de->d_name.name;
int len = de->d_name.len;
int error, rehash = 0;
int error;
ENTRY;
coda_vfs_stat.rmdir++;
......@@ -535,24 +535,13 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
if (len > CFS_MAXNAMLEN)
return -ENAMETOOLONG;
error = -EBUSY;
if (de->d_count > 1) {
/* Attempt to shrink child dentries ... */
shrink_dcache_parent(de);
if (de->d_count > 1)
return error;
}
/* Drop the dentry to force a new lookup */
if (!list_empty(&de->d_hash)) {
d_drop(de);
rehash = 1;
}
if (!list_empty(&de->d_hash))
return -EBUSY;
/* update i_nlink and free the inode before unlinking;
if rmdir fails a new lookup set i_nlink right.*/
if (de->d_inode->i_nlink)
de->d_inode->i_nlink --;
d_delete(de);
error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
......@@ -561,10 +550,6 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
return error;
}
if (rehash)
d_add(de, NULL);
/* XXX how can mtime be set? */
return 0;
}
......
......@@ -661,27 +661,11 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
if (le32_to_cpu(de->inode) != inode->i_ino)
goto end_rmdir;
/*
* Prune any child dentries so that this dentry becomes negative.
*/
if (dentry->d_count > 1)
shrink_dcache_parent(dentry);
if (!empty_dir (inode))
retval = -ENOTEMPTY;
else if (le32_to_cpu(de->inode) != inode->i_ino)
retval = -ENOENT;
else {
if (dentry->d_count > 1) {
/*
* Are we deleting the last instance of a busy directory?
* Better clean up if so.
*
* Make directory empty (it will be truncated when finally
* dereferenced). This also inhibits ext2_add_entry.
*/
inode->i_size = 0;
}
retval = ext2_delete_entry (de, bh);
dir->i_version = ++event;
}
......@@ -698,6 +682,7 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
inode->i_nlink);
inode->i_version = ++event;
inode->i_nlink = 0;
inode->i_size = 0;
mark_inode_dirty(inode);
dir->i_nlink--;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
......
......@@ -352,7 +352,7 @@ int hfs_rmdir(struct inode * parent, struct dentry *dentry)
goto hfs_rmdir_put;
error = -EBUSY;
if (dentry->d_count > 1)
if (!list_empty(&dentry->d_hash))
goto hfs_rmdir_put;
if (/* we only have to worry about 2 and 3 for mount points */
......
......@@ -452,7 +452,7 @@ int minix_rmdir(struct inode * dir, struct dentry *dentry)
retval = -ENOENT;
goto end_rmdir;
}
if (dentry->d_count > 1) {
if (!list_empty(&dentry->d_hash)) {
retval = -EBUSY;
goto end_rmdir;
}
......
......@@ -452,8 +452,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
if (res)
goto rmdir_done;
res = -EBUSY;
shrink_dcache_parent(dentry);
if (dentry->d_count > 1) {
if (!list_empty(&dentry->d_hash)) {
#ifdef MSDOS_DEBUG
printk("msdos_rmdir: %s/%s busy, d_count=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
......
......@@ -881,7 +881,6 @@ static inline int do_rmdir(const char * name)
error = -ENOENT;
if (!dentry->d_inode)
goto exit;
/*
* The dentry->d_count stuff confuses d_delete() enough to
* not kill the inode from under us while it is locked. This
......@@ -919,8 +918,29 @@ static inline int do_rmdir(const char * name)
DQUOT_INIT(dir->d_inode);
if (dentry->d_count > 1)
/*
* We try to drop the dentry early: we should have
* a usage count of 2 if we're the only user of this
* dentry, and if that is true (possibly after pruning
* the dcache), then we drop the dentry now.
*
* A low-level filesystem can, if it choses, legally
* do a
*
* if (!list_empty(&dentry->d_hash))
* return -EBUSY;
*
* if it cannot handle the case of removing a directory
* that is still in use by something else..
*/
switch (dentry->d_count) {
default:
shrink_dcache_parent(dentry);
if (dentry->d_count != 2)
break;
case 2:
d_drop(dentry);
}
error = dir->d_inode->i_op->rmdir(dir->d_inode, dentry);
......
......@@ -24,11 +24,6 @@
#include <linux/ncp_fs.h>
#include "ncplib_kernel.h"
#ifndef shrink_dcache_parent
#define shrink_dcache_parent(dentry) shrink_dcache_sb((dentry)->d_sb)
#endif
struct ncp_dirent {
struct nw_info_struct i;
struct nw_search_sequence s; /* given back for i */
......@@ -999,17 +994,14 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
printk(KERN_WARNING "ncp_rmdir: inode is NULL or not a directory\n");
goto out;
}
error = -EIO;
if (!ncp_conn_valid(NCP_SERVER(dir)))
goto out;
if (dentry->d_count > 1)
{
shrink_dcache_parent(dentry);
error = -EBUSY;
if (dentry->d_count > 1)
goto out;
}
error = -EBUSY;
if (!list_empty(&dentry->d_hash))
goto out;
strncpy(_name, dentry->d_name.name, dentry->d_name.len);
_name[dentry->d_name.len] = '\0';
......@@ -1023,7 +1015,6 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
if (!result)
{
ncp_invalid_dir_cache(dir);
d_delete(dentry);
error = 0;
}
out:
......
......@@ -721,7 +721,7 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
*/
static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error, rehash = 0;
int error;
dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
dir->i_dev, dir->i_ino, dentry->d_name.name);
......@@ -731,39 +731,24 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
goto out;
error = -EBUSY;
if (dentry->d_count > 1) {
/* Attempt to shrink child dentries ... */
shrink_dcache_parent(dentry);
if (dentry->d_count > 1)
goto out;
}
if (!list_empty(&dentry->d_hash))
goto out;
#ifdef NFS_PARANOIA
if (dentry->d_inode->i_count > 1)
printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
dentry->d_inode->i_count, dentry->d_inode->i_nlink);
#endif
/*
* Unhash the dentry while we remove the directory.
*/
if (!list_empty(&dentry->d_hash)) {
d_drop(dentry);
rehash = 1;
}
/*
* Update i_nlink and free the inode before unlinking.
*/
if (dentry->d_inode->i_nlink)
dentry->d_inode->i_nlink --;
d_delete(dentry);
nfs_invalidate_dircache(dir);
error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name);
if (!error) {
if (rehash)
d_add(dentry, NULL);
nfs_renew_times(dentry);
}
out:
return error;
}
......
......@@ -199,7 +199,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
goto end_rmdir;
}
#endif
if (dentry->d_count > 1) {
if (!list_empty(&dentry->d_hash)) {
retval = -EBUSY;
goto end_rmdir;
}
......
......@@ -479,22 +479,15 @@ smb_rmdir(struct inode *dir, struct dentry *dentry)
smb_close(inode);
/*
* Prune any child dentries so this dentry can become negative.
* Check that nobody else is using the directory..
*/
if (dentry->d_count > 1) {
shrink_dcache_parent(dentry);
error = -EBUSY;
if (dentry->d_count > 1)
goto out;
}
error = -EBUSY;
if (!list_empty(&dentry->d_hash))
goto out;
smb_invalid_dir_cache(dir);
error = smb_proc_rmdir(dentry);
if (!error)
{
smb_renew_times(dentry);
d_delete(dentry);
}
out:
return error;
}
......
......@@ -1008,8 +1008,7 @@ int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry)
goto out;
ret = -EBUSY;
shrink_dcache_parent(dentry);
if (dentry->d_count > 1)
if (!list_empty(&dentry->d_hash))
goto out;
/* check the sticky bit */
......@@ -1065,15 +1064,6 @@ demd->d_parent->d_name.name, demd->d_name.name, err);
else
d_drop(temp);
/* Check again for a busy dentry */
ret = -EBUSY;
shrink_dcache_parent(dentry);
if (dentry->d_count > 1) {
printk("umsdos_rmdir: %s/%s busy\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
goto out_dput;
}
/*
* Attempt to remove the msdos name.
*/
......@@ -1090,11 +1080,8 @@ printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret);
/* dput() temp if we didn't do it above */
out_dput:
if (temp != dentry) {
if (temp != dentry)
dput(temp);
if (!ret)
d_delete (dentry);
}
out:
Printk (("umsdos_rmdir %d\n", ret));
......
......@@ -156,11 +156,8 @@ static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
goto out;
ret = -EBUSY;
if (dentry->d_count > 1) {
shrink_dcache_parent(dentry);
if (dentry->d_count > 1)
goto out;
}
if (!list_empty(&dentry->d_hash))
goto out;
ret = msdos_rmdir (dir, dentry);
if (ret != -ENOTEMPTY)
......
......@@ -1422,6 +1422,8 @@ static int vfat_rmdir_free_ino(struct inode *dir,struct buffer_head *bh,
if (dir->i_dev != dentry->d_inode->i_dev || dir == dentry->d_inode) {
return -EBUSY;
}
if (!list_empty(&dentry->d_hash))
return -EBUSY;
res = vfat_empty(dentry->d_inode);
if (res) {
......@@ -1508,18 +1510,16 @@ static void drop_replace_inodes(struct dentry *dentry, struct inode *inode)
tmp = next;
next = tmp->next;
alias = list_entry(tmp, struct dentry, d_alias);
if (alias == dentry)
continue;
if (inode) {
list_del(&alias->d_alias);
iput(alias->d_inode);
d_instantiate(alias, inode);
/* dentry is already accounted for */
if (alias != dentry) {
inode->i_count++;
}
}
if (alias != dentry) {
d_drop(alias);
inode->i_count++;
}
d_drop(alias);
}
}
}
......@@ -1551,10 +1551,12 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
{
int res;
PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
res = vfat_rmdirx(dir, dentry);
if (res >= 0) {
drop_replace_inodes(dentry, NULL);
d_delete(dentry);
res = -EBUSY;
if (list_empty(&dentry->d_hash)) {
res = vfat_rmdirx(dir, dentry);
if (res >= 0)
drop_replace_inodes(dentry, NULL);
}
return res;
}
......
......@@ -34,7 +34,7 @@
* Version
*/
#define JS_VERSION 0x01020c
#define JS_VERSION 0x01020d
/*
* Types and constants for reading from /dev/js
......@@ -179,18 +179,23 @@ typedef struct { int something; } spinlock_t;
#ifdef USE_PARPORT
#include <linux/parport.h>
#define JS_PAR_STATUS(y) parport_read_status(y->port)
#define JS_PAR_DATA_IN(y) parport_read_data(y->port)
#define JS_PAR_DATA_OUT(x,y) parport_write_data(y->port, x)
#define JS_PAR_STATUS(y) parport_read_status(y->port)
#define JS_PAR_CTRL_IN(y) parport_read_control(y->port)
#define JS_PAR_CTRL_OUT(x,y) parport_write_control(y->port, x)
#define JS_PAR_ECTRL_OUT(x,y) parport_write_econtrol(y->port, x)
#else
#define JS_PAR_STATUS(y) inb(y+1)
#define JS_PAR_DATA_IN(y) inb(y)
#define JS_PAR_DATA_OUT(x,y) outb(x,y)
#define JS_PAR_STATUS(y) inb(y+1)
#define JS_PAR_CTRL_IN(y) inb(y+2)
#define JS_PAR_CTRL_OUT(x,y) outb(x,y+2)
#define JS_PAR_ECTRL_OUT(x,y) outb(x,y+0x402)
#endif
#define JS_PAR_STATUS_INVERT (0x80)
#define JS_PAR_CTRL_INVERT (0x04)
/*
* Internal types
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment