Commit 1d3f1e5e authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.99pre4-5

parent 96d333c6
...@@ -1570,6 +1570,15 @@ S: 2200 Mission College Blvd ...@@ -1570,6 +1570,15 @@ S: 2200 Mission College Blvd
S: Santa Clara, CA 95052 S: Santa Clara, CA 95052
S: USA S: USA
N: Petko Manolov
E: petkan@spct.net
D: USB ethernet (pegasus) driver
D: optimizing i[45]86 string routines
D: i386 task swithing hacks
S: 5, Vrah Mancho str.
S: 1324 Sofia
S: Bulgaria
N: Martin Mares N: Martin Mares
E: mj@suse.cz E: mj@suse.cz
E: mj@ucw.cz E: mj@ucw.cz
......
...@@ -9680,11 +9680,18 @@ CONFIG_USB_OV511 ...@@ -9680,11 +9680,18 @@ CONFIG_USB_OV511
USB ADMtek Pegasus-based ethernet device support USB ADMtek Pegasus-based ethernet device support
CONFIG_USB_PEGASUS CONFIG_USB_PEGASUS
Say Y if you want to use your USB ethernet device. Note that Say Y if you want to use your USB ethernet device. Supported
the code is still experimental. If you have devices with vendor cards until now are:
IDs other than ADMtek's, you should change/add them in the Accton 10/100
driver code and send a message to me (petkan@spct.net) for Billington USB-100
update. Corega FEter USB-TX
MELCO/BUFFALO LUA-TX
D-Link DSB-650TX, DSB-650TX-PNA
Linksys USB100TX
SNC 202
If you have devices with vendor IDs other than noted above
you should add them in the driver code and send a message
to me (petkan@spct.net) for update.
This code is also available as a module ( = code which can be This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want). inserted in and removed from the running kernel whenever you want).
......
The ACM driver works with modems and ISDN TAs that use the USB Abstract Linux ACM driver v0.16
Control Model standard. (c) 1999 Vojtech Pavlik <vojtech@suse.cz>
Sponsored by SuSE
**************************** ----------------------------------------------------------------------------
Test it:
Watch out, the driver is not stable and tested. Sync often, make backups, 0. Disclaimer
most importand: don't blame me... ~~~~~~~~~~~~~
This program is free software; you can redistribute it and/or modify it
Create device files: under the terms of the GNU General Public License as published by the Free
mknod /dev/ttyACM0 c 166 0 Software Foundation; either version 2 of the License, or (at your option)
mknod /dev/ttyACM1 c 166 1 any later version.
mknod /dev/ttyACM2 c 166 2
mknod /dev/ttyACM3 c 166 3 This program is distributed in the hope that it will be useful, but
Compile a kernel with support for your host controller (uhci only for now!) WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
and support for ACM. Boot this kernel. If you connect your device to the or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
USB bus you should see messages like the following: more details.
Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1 You should have received a copy of the GNU General Public License along
Jul 19 20:14:29 office kernel: Found 02:09 with this program; if not, write to the Free Software Foundation, Inc., 59
Jul 19 20:14:29 office kernel: Found 04:09 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Jul 19 20:14:29 office kernel: Found 05:07
Jul 19 20:14:29 office last message repeated 2 times Should you need to contact me, the author, you can do so either by e-mail
Jul 19 20:14:29 office kernel: parsed = 39 len = 67 - mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping Ucitelska 1576, Prague 8, 182 00 Czech Republic
Jul 19 20:14:29 office kernel: 0 09
Jul 19 20:14:29 office kernel: 1 02 For your convenience, the GNU General Public License version 2 is included
Jul 19 20:14:29 office kernel: 2 43 in the package: See the file COPYING.
Jul 19 20:14:29 office kernel: 3 00
Jul 19 20:14:29 office kernel: 4 02 1. Usage
Jul 19 20:14:29 office kernel: 5 02 ~~~~~~~~
Jul 19 20:14:29 office kernel: 6 04 The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal
Jul 19 20:14:29 office kernel: 7 60 adapters that conform to the Universal Serial Bus Communication Device Class
Jul 19 20:14:29 office kernel: 8 00 Abstract Control Model (USB CDC ACM) specification.
Jul 19 20:14:29 office kernel: Found 04:09
Jul 19 20:14:29 office kernel: Found 02:09 Many modems do, here is a list of those I know of:
Jul 19 20:14:29 office kernel: Found 04:09
Jul 19 20:14:29 office kernel: Found 05:07 3Com OfficeConnect 56k
Jul 19 20:14:29 office kernel: Found 04:09 3Com Voice FaxModem Pro
Jul 19 20:14:29 office kernel: Found 05:07 3Com Sportster
Jul 19 20:14:29 office kernel: Found 05:07 MultiTech MultiModem 56k
Jul 19 20:14:29 office kernel: parsed = 67 len = 0 Zoom 2986L FaxModem
Jul 19 20:14:29 office kernel: getstringtable Compaq 56k FaxModem
Jul 19 20:14:29 office kernel: acm_probe ELSA Microlink 56k
Jul 19 20:14:29 office kernel: USB ACM found
I know of one ISDN TA that does work with the acm driver:
Watch out for the line:
Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1 3Com USR ISDN Pro TA
and the line:
Jul 19 20:14:29 office kernel: USB ACM found Unfortunately many modems and most ISDN TAs use proprietary interfaces and
These two lines show that the device was seen by the usb host controller and thus won't work with this drivers. Check for ACM compliance before buying.
then recognized by the acm driver as a valid device.
The driver (with devfs) creates these devices in /dev/usb/acm:
If you use a terminal emulation software like minicom with /dev/ttyACM0 you
should be able to send AT commands to your device and get responses. I've crw-r--r-- 1 root root 166, 0 Apr 1 10:49 0
been able to do zmodem downloads to another pc. However downloads from one crw-r--r-- 1 root root 166, 1 Apr 1 10:49 1
ISDN TA to another ISDN TA connected to the same PC didn't work. Don't crw-r--r-- 1 root root 166, 2 Apr 1 10:49 2
know why. Flow control is not finised after all and i'd guess there might
be problems on heavily loades PCs. I also did some tests with ppp but i'm And so on, up to 31, with the limit being possible to change in acm.c to up
not finised with this. There might be a chance to get it working. However to 256, so you can use up to 256 USB modems with one computer (you'll need
i'd like to know if your device is recognized as an ACM device. I'm also three USB cards for that, though).
interested if the thing is stable or if it crashes.
(should i say how it crases?) If you don't use devfs, then you can create device nodes with the same
minor/major numbers anywhere you want, but either the above location or
You should be able to add and remove devices from the bus. The driver will /dev/usb/ttyACM0 is preferred.
always try to fill up unused ttys. This means if you hotplug devices their
order may have changed after reboot. This is not the behaviour Linus liked To use the modems you need these modules loaded:
to see but it's ok for now. (I hope ;-)
usbcore.o
Please report your experiences to me: usb-[uo]hci.o or uhci.o
fuerst@in.tum.de acm.o
*************************** After that, the modem[s] should be accessible. You should be able to use
I've tested it with: minicom, ppp and mgetty with them.
3Com ISDN Pro TA.
2. Verifying that it works
It should work with (That means i know these devices conform to ACM): ~~~~~~~~~~~~~~~~~~~~~~~~~~
3Com Office Connect Modem The first step would be to check /proc/bus/usb/devices, it should look
3Com Sportster USB (I think that's what it's called) like this:
*************************** T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
Many thanks to 3Com which did not only support me with hardware but also B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0
with technical support in USB questions. They also allowed me to do tests in D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
their lab. Great! P: Vendor=0000 ProdID=0000 Rev= 0.00
S: Product=USB UHCI Root Hub
*************************** S: SerialNumber=6800
Known bugs: C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
Flow control not tested (likely not to work) I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
Some tty function calls not implemented (putchar, etc...) E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 ) T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
Not all mem is freed at close (need terminate irq in hcd) D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2
P: Vendor=04c1 ProdID=008f Rev= 2.07
*************************** S: Manufacturer=3Com Inc.
Have fun, S: Product=3Com U.S. Robotics Pro ISDN TA
Armin Fuerst S: SerialNumber=UFT53A49BVT7
C: #Ifs= 1 Cfg#= 1 Atr=60 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=acm
E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
C:* #Ifs= 2 Cfg#= 2 Atr=60 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm
E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
The presence of these three lines (and the Cls= 'comm' and 'data' classes)
is important, it means it's an ACM device. The Driver=acm means the acm
driver is used for the device. If you see only Cls=ff(vend.) then you're out
of luck, you have a device with vendor specific-interface.
D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm
In the system log you should see:
usb.c: USB new device connect, assigned device number 2
usb.c: kmalloc IF c7691fa0, numif 1
usb.c: kmalloc IF c7b5f3e0, numif 2
usb.c: skipped 4 class/vendor specific interface descriptors
usb.c: new device strings: Mfr=1, Product=2, SerialNumber=3
usb.c: USB device number 2 default language ID 0x409
Manufacturer: 3Com Inc.
Product: 3Com U.S. Robotics Pro ISDN TA
SerialNumber: UFT53A49BVT7
acm.c: probing config 1
acm.c: probing config 2
ttyACM0: USB ACM device
acm.c: acm_control_msg: rq: 0x22 val: 0x0 len: 0x0 result: 0
acm.c: acm_control_msg: rq: 0x20 val: 0x0 len: 0x7 result: 7
usb.c: acm driver claimed interface c7b5f3e0
usb.c: acm driver claimed interface c7b5f3f8
usb.c: acm driver claimed interface c7691fa0
If all this seems to be OK, fire up minicom and set it to talk to the ttyACM
device and try typing 'at'. If it responds with 'OK', then everything is
working.
Linux HID driver v0.8
(c) 1999 Vojtech Pavlik <vojtech@suse.cz>
(c) 1999 Andreas Gal <agal@uwsp.edu>
Sponsored by SuSE
----------------------------------------------------------------------------
0. Disclaimer
~~~~~~~~~~~~~
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA
Should you need to contact me, the author, you can do so either by e-mail
- mail your message to <vojtech@suse.cz>, or by paper mail: Vojtech Pavlik,
Ucitelska 1576, Prague 8, 182 00 Czech Republic
For your convenience, the GNU General Public License version 2 is included
in the package: See the file COPYING.
1. Introduction
~~~~~~~~~~~~~~~
This is a driver for USB devices conforming to the USB HID (Human Input
Device) standard. These devices include namely keyboards, mice and
joysticks.
However many other devices (monitors, speakers, UPSs ...) also communicate
through the same protocol, which makes its specification somewhat bloated.
This isn't a problem, though, because the driver doesn't need to know about
all the possible devices it can control, and can just parse the protocol and
leave the rest of the job (for example understanding what the UPS wants to
say) to the userland.
Because of this, the USB HID driver has two interfaces. One is via the
proc filesystem, allowing userland applications send and read arbitrary
reports to and from a connected USB device. The other is via a very simple
yet generic input device driver, which dispatches input events (keystrokes,
mouse or joystick movements) to specific, backward compatible userland
interfaces. This way a PS/2 mouse, an AT keyboard or a Linux joystick driver
interface are emulated, and allow applications to immediately work with USB
mice, USB keyboards and USB joysticks without any changes.
The input driver is aimed for a little more than USB device handling in
the future, though. It's generic enough so that it can be used for any
mouse, keyboard or joystick (and more, of course). A PS/2 mouse driver, a
serial mouse, Sun mouse, and most of the busmouse drivers were rewritten to
use this as well as the AT keyboard and Sun keyboard drivers. This will
hopefully allow conversion of all Linux keyboard and mouse and joystick
drivers to this scheme.
This effort has it's home page at:
http://www.suse.cz/development/input/
You'll find both the latest HID driver and the complete Input driver there.
There is also a mailing list for this:
listproc@atrey.karlin.mff.cuni.cz
Send "subscribe linux-joystick Your Name" to subscribe to it.
2. Usage
~~~~~~~~
Since the driver comes with recent 2.3 kernels, all that's needed to use
it is to enable it either as a module or compiled-in into the kernel.
After that, after reboot (and possibly also inserting the USB and HID
modules) the following will happen:
* If you selected keyboard support, all USB keystrokes will be also routed
to the Linux keyboard driver as if being input through the ordinary system
keyboard.
* If you selected mouse support, there will be (one or more) simulated PS/2
mouse devices on major 10, minor 32, 33 and more. These simulated mice can
in addition to a standard 3-button PS/2 mouse behave like MS Intellimice,
with a wheel. If you want to use the wheel, just specify '-t imps2' to gpm
and 'Protocol "ImPS/2"' to X, and it will work. A single emulated mouse
device can be open by any number of processes (unlike the /dev/psaux), and
for each of them the emulation is separate, each can use a different mode.
The mousedev driver, which emulates the mice, can also emulate a Genius
NewScroll 5 buttons-and-a-wheel mouse, if you set it to a Genius PS/2
mode ('-t netmouse' 'Protocol "NetMousePS/2"'). However, not gpm, nor X
can decode the 5 buttons yet, so this isn't very useful right now.
* If you selected joystick support, the driver will take over major 15, the
joystick major number, and will emulate joysticks on it. This means the
normal joystick driver can't be used together with it (now, after the
normal joystick drivers are converted to the input scheme, all will work
nicely together). Also, you'll probably need to calibrate your joystick
manually ('man jscal') to be able to use it, because the USB
autocalibration is far from perfect yet.
* If you selected event device support, there will be devices on major 10,
minors 64, 65 and more for each input device connected through this
driver. These devices output raw events the input driver dispatches. Each
has a timestamp. This hopefully will be THE way X will talk to keyboard
and mice, because it's hardware independent, and not limited by existing
de-facto standards.
3. Verifying if it works
~~~~~~~~~~~~~~~~~~~~~~~~
Typing a couple keys on the keyboard should be enough to check that a USB
keyboard works and is correctly connected to the kernel keyboard driver.
Doing a cat /dev/hidmouse (c, 10, 32) will verify that a mouse is also
emulated, characters should appear if you move it.
You can test the joystick emulation with the 'jstest' utility, available
in the joystick package (see Documentation/joystick.txt).
You can test the event devics with the 'evtest' utitily available on the
input driver homepage (see the URL above).
4. FAQ
~~~~~~
Q: Why aren't any questions here yet?
A: Because none were frequent enough yet.
5. Event interface
~~~~~~~~~~~~~~~~~~
Should you want to add event device support into any application (X, gpm,
svgalib ...) I (vojtech@suse.cz) will be happy to provide you any help I
can. Here goes a description of the current state of things, which is going
to be extended, but not changed incompatibly as time goes:
You can use blocking and nonblocking reads, also select() on the
/dev/inputX devices, and you'll always get a whole number of input events on
a read. Their layout is:
struct input_event {
struct timeval time;
unsigned short type;
unsigned short code;
unsigned int value;
};
'time' is the timestamp, it returns the time at which the event happened.
Type is for example EV_REL for relative momement, REL_KEY for a keypress or
release. More types are defined in include/linux/input.h.
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
list is in include/linux/input.h.
'value' is the value the event carries. Either a relative change for
EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
release, 1 for keypress and 2 for autorepeat.
6. Proc interface
~~~~~~~~~~~~~~~~~
For HID-specific devices there is also the /proc interface. It isn't
present in this release yet, though, so it's description will appear here
together with the code in the driver.
This diff is collapsed.
...@@ -5,44 +5,17 @@ Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC ...@@ -5,44 +5,17 @@ Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
Author: Mark McClelland Author: Mark McClelland
Homepage: http://alpha.dyndns.org/ov511 Homepage: http://alpha.dyndns.org/ov511
NEW IN THIS VERSION:
o Support for OV511+
o Support for OV7620
INTRODUCTION: INTRODUCTION:
This is a preliminary version of my OV511 Linux device driver. Currently, it can This is a preliminary version of my OV511 Linux device driver. Currently, it can
grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or
xawtv. Other utilities may work but have not yet been tested. xawtv. Other utilities may work but have not yet been tested.
NEW IN THIS VERSION: Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. The
o Autoadjust disable works, but is not perfect yet
o Partial support for OV511+
o Detection and support for OV7610, OV7620, and OV7620AE sensors
o Various code cleanups and improvements
KNOWN CAMERAS:
____________________________________________________________________
Manufacturer | Model | ID | Bridge | Sensor | Status
--------------+-----------------+-----+--------+----------+-----------
MediaForte | MV300 | 0 | OV511 | OV7610 * | Working
Aiptek | HyperVCam ? | 0 | OV511 | OV7610 * | Working
NetView | NV300M | 0 | OV511 | OV7610 * | Working
D-Link | DSB-C300 | 3 | OV511 | OV7620AE | Working
Hawking Tech. | ??? | 3 | OV511 | OV7610 * | Working
??? | Generic | 4 | OV511 | OV7610 * | Untested
Puretek | PT-6007 | 5 | OV511 | OV7610 * | Working
Creative Labs | WebCam 3 | 21 | OV511 | OV7610 * | Working
??? | Koala-Cam | 36 | OV511 | OV7610 * | Untested
Lifeview | USB Life TV | 38 | OV511 | N/A | Unsupported
Lifeview | RoboCam | 100 | OV511 | OV7610 * | Untested
AverMedia | InterCam Elite | 102 | OV511 | OV7610 * | Working
MediaForte | MV300 | 112 | OV511 | OV7610 * | Working
Omnivision | OV7110 EV board | 112 | OV511 | OV7110 | Working
---------------------------------------------------------------------
(*) These have not been verified. If you have one of these, please report
the sensor type to me.
NOTE - the OV511+ is not yet supported
Any camera using the OV511 and the OV7610 or OV7620AE CCD should work. The
driver only detects known cameras though, based on their custom id number. If driver only detects known cameras though, based on their custom id number. If
you have a currently unsupported camera, the ID number should be reported to you you have a currently unsupported camera, the ID number should be reported to you
in the kernel logs. Please send me the model, manufacturer and ID number and I in the kernel logs. Please send me the model, manufacturer and ID number and I
...@@ -183,7 +156,6 @@ EXPERIMENTAL FEATURES: ...@@ -183,7 +156,6 @@ EXPERIMENTAL FEATURES:
o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
corrupted frames. corrupted frames.
o Snapshot mode (only works with some read() based apps; see below for more) o Snapshot mode (only works with some read() based apps; see below for more)
o OV511+ support; not complete yet.
TODO: TODO:
o Fix the noise / grainy image problem. o Fix the noise / grainy image problem.
...@@ -201,7 +173,6 @@ TODO: ...@@ -201,7 +173,6 @@ TODO:
o Get hue (red/blue channel balance) adjustment working (in ov511_get_picture() o Get hue (red/blue channel balance) adjustment working (in ov511_get_picture()
and ov511_set_picture()) and ov511_set_picture())
o Get autoadjust disable working o Get autoadjust disable working
o OV7620 support
o V4L2 support (Probably not until it goes into the kernel) o V4L2 support (Probably not until it goes into the kernel)
o Fix I2C initialization. Some people are reporting problems with reading the o Fix I2C initialization. Some people are reporting problems with reading the
7610 registers. This could be due to timing differences, an excessive I2C 7610 registers. This could be due to timing differences, an excessive I2C
......
...@@ -822,8 +822,8 @@ W: http://www-jcr.lmh.ox.ac.uk/~pnp/ ...@@ -822,8 +822,8 @@ W: http://www-jcr.lmh.ox.ac.uk/~pnp/
S: Maintained S: Maintained
PPP PROTOCOL DRIVERS AND COMPRESSORS PPP PROTOCOL DRIVERS AND COMPRESSORS
P: Al Longyear P: Paul Mackerras
M: longyear@pobox.com M: paulus@linuxcare.com
L: linux-ppp@vger.rutgers.edu L: linux-ppp@vger.rutgers.edu
S: Maintained S: Maintained
......
...@@ -44,11 +44,17 @@ if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then ...@@ -44,11 +44,17 @@ if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then
define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_ALIGNMENT_16 y
fi fi
if [ "$CONFIG_M586TSC" = "y" -o "$CONFIG_MK6" = "y" ]; then if [ "$CONFIG_M586TSC" = "y" ]; then
define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_TSC y
fi fi
if [ "$CONFIG_MK6" = "y" ]; then
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_USE_3DNOW y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
fi
if [ "$CONFIG_M686" = "y" ]; then if [ "$CONFIG_M686" = "y" ]; then
define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_GOOD_APIC y
......
This diff is collapsed.
...@@ -311,21 +311,19 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -311,21 +311,19 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
if (!acm || !acm->used) return; if (!acm || !acm->used) return;
MOD_DEC_USE_COUNT; if (!--acm->used) {
if (acm->dev) {
if (--acm->used) return; acm_set_control(acm, acm->ctrlout = 0);
usb_unlink_urb(&acm->ctrlurb);
if (acm->dev) { usb_unlink_urb(&acm->writeurb);
acm_set_control(acm, acm->ctrlout = 0); usb_unlink_urb(&acm->readurb);
usb_unlink_urb(&acm->ctrlurb); } else {
usb_unlink_urb(&acm->writeurb); tty_unregister_devfs(&acm_tty_driver, acm->minor);
usb_unlink_urb(&acm->readurb); acm_table[acm->minor] = NULL;
return; kfree(acm);
}
} }
MOD_DEC_USE_COUNT;
tty_unregister_devfs(&acm_tty_driver, acm->minor);
acm_table[acm->minor] = NULL;
kfree(acm);
} }
static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
......
...@@ -56,7 +56,7 @@ struct evdev_list { ...@@ -56,7 +56,7 @@ struct evdev_list {
struct evdev_list *next; struct evdev_list *next;
}; };
static struct evdev *evdev_table[BITS_PER_LONG] = { NULL, /* ... */ }; static struct evdev *evdev_table[EVDEV_MINORS] = { NULL, /* ... */ };
static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{ {
...@@ -119,9 +119,12 @@ static int evdev_open(struct inode * inode, struct file * file) ...@@ -119,9 +119,12 @@ static int evdev_open(struct inode * inode, struct file * file)
if (i > EVDEV_MINORS || !evdev_table[i]) if (i > EVDEV_MINORS || !evdev_table[i])
return -ENODEV; return -ENODEV;
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) MOD_INC_USE_COUNT;
return -ENOMEM;
if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(list, 0, sizeof(struct evdev_list)); memset(list, 0, sizeof(struct evdev_list));
list->evdev = evdev_table[i]; list->evdev = evdev_table[i];
...@@ -132,7 +135,6 @@ static int evdev_open(struct inode * inode, struct file * file) ...@@ -132,7 +135,6 @@ static int evdev_open(struct inode * inode, struct file * file)
list->evdev->used++; list->evdev->used++;
MOD_INC_USE_COUNT;
return 0; return 0;
} }
......
...@@ -1288,7 +1288,7 @@ static void hid_init_input(struct hid_device *hid) ...@@ -1288,7 +1288,7 @@ static void hid_init_input(struct hid_device *hid)
hid_configure_usage(hid, report->field[i], report->field[i]->usage + j); hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
if (k == HID_INPUT_REPORT) { if (k == HID_INPUT_REPORT) {
usb_set_idle(hid->dev, hid->ifnum, report->id, 0); usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
hid_read_report(hid, report); hid_read_report(hid, report);
} }
} }
......
...@@ -78,7 +78,7 @@ struct joydev_list { ...@@ -78,7 +78,7 @@ struct joydev_list {
struct joydev_list *next; struct joydev_list *next;
}; };
static struct joydev *joydev_table[BITS_PER_LONG]; static struct joydev *joydev_table[JOYDEV_MINORS];
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_SUPPORTED_DEVICE("input/js"); MODULE_SUPPORTED_DEVICE("input/js");
...@@ -186,8 +186,12 @@ static int joydev_open(struct inode *inode, struct file *file) ...@@ -186,8 +186,12 @@ static int joydev_open(struct inode *inode, struct file *file)
if (i > JOYDEV_MINORS || !joydev_table[i]) if (i > JOYDEV_MINORS || !joydev_table[i])
return -ENODEV; return -ENODEV;
if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) MOD_INC_USE_COUNT;
if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM; return -ENOMEM;
}
memset(list, 0, sizeof(struct joydev_list)); memset(list, 0, sizeof(struct joydev_list));
list->joydev = joydev_table[i]; list->joydev = joydev_table[i];
...@@ -198,7 +202,6 @@ static int joydev_open(struct inode *inode, struct file *file) ...@@ -198,7 +202,6 @@ static int joydev_open(struct inode *inode, struct file *file)
list->joydev->used++; list->joydev->used++;
MOD_INC_USE_COUNT;
return 0; return 0;
} }
......
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
* The driver supports only one camera. * The driver supports only one camera.
* *
* version 0.7.1 * version 0.7.1
* MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload
* problems when compiled as Module.
* (04/04/2000)
*
* The mdc800 driver gets assigned the USB Minor 32-47. The Registration * The mdc800 driver gets assigned the USB Minor 32-47. The Registration
* was updated to use these values. * was updated to use these values.
* (26/03/2000) * (26/03/2000)
...@@ -77,12 +81,12 @@ ...@@ -77,12 +81,12 @@
#define MDC800_PRODUCT_ID 0xa800 #define MDC800_PRODUCT_ID 0xa800
/* Timeouts (msec) */ /* Timeouts (msec) */
#define TO_READ_FROM_IRQ 4000 #define TO_READ_FROM_IRQ 4000
#define TO_GET_READY 2000 #define TO_GET_READY 2000
#define TO_DOWNLOAD_GET_READY 1500 #define TO_DOWNLOAD_GET_READY 1500
#define TO_DOWNLOAD_GET_BUSY 1500 #define TO_DOWNLOAD_GET_BUSY 1500
#define TO_WRITE_GET_READY 3000 #define TO_WRITE_GET_READY 3000
#define TO_DEFAULT_COMMAND 5000 #define TO_DEFAULT_COMMAND 5000
/* Minor Number of the device (create with mknod /dev/mustek c 180 32) */ /* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
#define MDC800_DEVICE_MINOR_BASE 32 #define MDC800_DEVICE_MINOR_BASE 32
...@@ -517,11 +521,20 @@ static int mdc800_getAnswerSize (char command) ...@@ -517,11 +521,20 @@ static int mdc800_getAnswerSize (char command)
static int mdc800_device_open (struct inode* inode, struct file *file) static int mdc800_device_open (struct inode* inode, struct file *file)
{ {
int retval=0; int retval=0;
MOD_INC_USE_COUNT;
if (mdc800->state == NOT_CONNECTED) if (mdc800->state == NOT_CONNECTED)
{
MOD_DEC_USE_COUNT;
return -EBUSY; return -EBUSY;
}
if (mdc800->open) if (mdc800->open)
{
MOD_DEC_USE_COUNT;
return -EBUSY; return -EBUSY;
}
mdc800->rw_lock=0; mdc800->rw_lock=0;
mdc800->in_count=0; mdc800->in_count=0;
...@@ -538,10 +551,10 @@ static int mdc800_device_open (struct inode* inode, struct file *file) ...@@ -538,10 +551,10 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
if (usb_submit_urb (mdc800->irq_urb)) if (usb_submit_urb (mdc800->irq_urb))
{ {
err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status); err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
MOD_DEC_USE_COUNT;
return -EIO; return -EIO;
} }
MOD_INC_USE_COUNT;
mdc800->open=1; mdc800->open=1;
dbg ("Mustek MDC800 device opened."); dbg ("Mustek MDC800 device opened.");
......
...@@ -70,7 +70,7 @@ struct mousedev_list { ...@@ -70,7 +70,7 @@ struct mousedev_list {
static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 }; static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 };
static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
static struct mousedev *mousedev_table[BITS_PER_LONG]; static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{ {
...@@ -177,9 +177,12 @@ static int mousedev_open(struct inode * inode, struct file * file) ...@@ -177,9 +177,12 @@ static int mousedev_open(struct inode * inode, struct file * file)
if (i > MOUSEDEV_MINORS || !mousedev_table[i]) if (i > MOUSEDEV_MINORS || !mousedev_table[i])
return -ENODEV; return -ENODEV;
if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) MOD_INC_USE_COUNT;
return -ENOMEM;
if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(list, 0, sizeof(struct mousedev_list)); memset(list, 0, sizeof(struct mousedev_list));
list->mousedev = mousedev_table[i]; list->mousedev = mousedev_table[i];
...@@ -189,7 +192,6 @@ static int mousedev_open(struct inode * inode, struct file * file) ...@@ -189,7 +192,6 @@ static int mousedev_open(struct inode * inode, struct file * file)
file->private_data = list; file->private_data = list;
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -360,19 +362,15 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev ...@@ -360,19 +362,15 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
printk(KERN_ERR "mousedev: no more free mousedev devices\n"); printk(KERN_ERR "mousedev: no more free mousedev devices\n");
return -1; return -1;
} }
#else
if (!mousedev_table[minor]) {
#endif
if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL))) if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
return -1; return -1;
memset(mousedev, 0, sizeof(struct mousedev)); memset(mousedev, 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev->wait); init_waitqueue_head(&mousedev->wait);
mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
#ifdef CONFIG_INPUT_MOUSEDEV_MIX mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
} else mousedev = mousedev_table[minor]; #else
mousedev = mousedev_table[0];
#endif #endif
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) { if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) {
...@@ -419,11 +417,24 @@ static struct input_handler mousedev_handler = { ...@@ -419,11 +417,24 @@ static struct input_handler mousedev_handler = {
static int __init mousedev_init(void) static int __init mousedev_init(void)
{ {
input_register_handler(&mousedev_handler); input_register_handler(&mousedev_handler);
#ifdef CONFIG_INPUT_MOUSEDEV_MIX
if (!(mousedev_table[0] = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
return -1;
memset(mousedev_table[0], 0, sizeof(struct mousedev));
init_waitqueue_head(&mousedev_table[0]->wait);
mousedev_table[0]->devfs = input_register_minor("mouse%d", 0, MOUSEDEV_MINOR_BASE);
mousedev_table[0]->used = 1;
#endif
return 0; return 0;
} }
static void __exit mousedev_exit(void) static void __exit mousedev_exit(void)
{ {
#ifdef CONFIG_INPUT_MOUSEDEV_MIX
input_unregister_minor(mousedev_table[0]->devfs);
kfree(mousedev_table[0]);
#endif
input_unregister_handler(&mousedev_handler); input_unregister_handler(&mousedev_handler);
} }
......
This diff is collapsed.
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
#include <linux/usb.h> #include <linux/usb.h>
static const char *version = __FILE__ ": v0.3.7 2000/03/23 Written by Petko Manolov (petkan@spct.net)\n"; static const char *version = __FILE__ ": v0.3.8 2000/04/04 Written by Petko Manolov (petkan@spct.net)\n";
#define PEGASUS_MTU 1500 #define PEGASUS_MTU 1500
#define PEGASUS_MAX_MTU 1536 #define PEGASUS_MAX_MTU 1536
#define SROM_WRITE 0x01 #define SROM_WRITE 0x01
#define SROM_READ 0x02 #define SROM_READ 0x02
#define PEGASUS_TX_TIMEOUT (HZ*5) #define PEGASUS_TX_TIMEOUT (HZ*5)
...@@ -55,14 +55,16 @@ MODULE_PARM(loopback, "i"); ...@@ -55,14 +55,16 @@ MODULE_PARM(loopback, "i");
static struct usb_eth_dev usb_dev_id[] = { static struct usb_eth_dev usb_dev_id[] = {
{"Billionton USB-100", 0x08dd, 0x0986, NULL}, {"Billionton USB-100", 0x08dd, 0x0986, NULL},
{"Corega FEter USB-TX", 0x7aa, 0x0004, NULL}, {"Corega FEter USB-TX", 0x7aa, 0x0004, NULL},
{"MELCO LUA-TX", 0x0411, 0x0001, NULL}, {"MELCO/BUFFALO LUA-TX", 0x0411, 0x0001, NULL},
{ "D-Link DSB-650TX", 0x2001, 0x4002, NULL }, {"D-Link DSB-650TX", 0x2001, 0x4001, NULL},
{ "D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL }, {"D-Link DSB-650TX", 0x2001, 0x4002, NULL},
{ "Linksys USB100TX", 0x066b, 0x2203, NULL }, {"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL},
{ "SMC 202 USB Ethernet", 0x0707, 0x0200, NULL }, {"Linksys USB100TX", 0x066b, 0x2203, NULL},
{ "ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, NULL }, {"Linksys USB100TX", 0x066b, 0x2204, NULL},
{ "Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL }, {"SMC 202 USB Ethernet", 0x0707, 0x0200, NULL},
{ NULL, 0, 0, NULL } {"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, NULL},
{"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL},
{NULL, 0, 0, NULL}
}; };
...@@ -387,7 +389,7 @@ static void pegasus_set_rx_mode(struct net_device *net) ...@@ -387,7 +389,7 @@ static void pegasus_set_rx_mode(struct net_device *net)
(net->flags & IFF_ALLMULTI)) { (net->flags & IFF_ALLMULTI)) {
pegasus_set_register(pegasus->usb, 0, 0xfa); pegasus_set_register(pegasus->usb, 0, 0xfa);
pegasus_set_register(pegasus->usb, 2, 0); pegasus_set_register(pegasus->usb, 2, 0);
info("%s: set allmulti", net->name); info("%s set allmulti", net->name);
} else { } else {
info("%s: set Rx mode", net->name); info("%s: set Rx mode", net->name);
} }
......
...@@ -160,10 +160,13 @@ static int usblp_open(struct inode *inode, struct file *file) ...@@ -160,10 +160,13 @@ static int usblp_open(struct inode *inode, struct file *file)
if (usblp->used) if (usblp->used)
return -EBUSY; return -EBUSY;
if ((retval = usblp_check_status(usblp))) MOD_INC_USE_COUNT;
if ((retval = usblp_check_status(usblp))) {
MOD_DEC_USE_COUNT;
return retval; return retval;
}
MOD_INC_USE_COUNT;
usblp->used = 1; usblp->used = 1;
file->private_data = usblp; file->private_data = usblp;
...@@ -179,17 +182,18 @@ static int usblp_release(struct inode *inode, struct file *file) ...@@ -179,17 +182,18 @@ static int usblp_release(struct inode *inode, struct file *file)
{ {
struct usblp *usblp = file->private_data; struct usblp *usblp = file->private_data;
MOD_DEC_USE_COUNT;
usblp->used = 0; usblp->used = 0;
if (usblp->dev) { if (usblp->dev) {
usb_unlink_urb(&usblp->readurb); usb_unlink_urb(&usblp->readurb);
usb_unlink_urb(&usblp->writeurb); usb_unlink_urb(&usblp->writeurb);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
usblp_table[usblp->minor] = NULL; usblp_table[usblp->minor] = NULL;
kfree(usblp); kfree(usblp);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* (C) Copyright (C) 1999, 2000 * (C) Copyright (C) 1999, 2000
* Greg Kroah-Hartman (greg@kroah.com) * Greg Kroah-Hartman (greg@kroah.com)
* Bill Ryder (bryder@sgi.com)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -11,6 +12,10 @@ ...@@ -11,6 +12,10 @@
* *
* See Documentation/usb/usb-serial.txt for more information on using this driver * See Documentation/usb/usb-serial.txt for more information on using this driver
* *
* (04/04/2000) Bill Ryder
* Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
* handled elsewhere in the serial driver chain).
*
* (03/30/2000) Bill Ryder * (03/30/2000) Bill Ryder
* Implemented lots of ioctls * Implemented lots of ioctls
* Fixed a race condition in write * Fixed a race condition in write
...@@ -284,7 +289,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, ...@@ -284,7 +289,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
unsigned char *first_byte = port->write_urb->transfer_buffer; unsigned char *first_byte = port->write_urb->transfer_buffer;
/* Was seeing a race here, got a read callback, then write callback before /* Was seeing a race here, got a read callback, then write callback before
hitting interuuptible_sleep_on - so wrapping in add_wait_queue stuff */ hitting interuptible_sleep_on - so wrapping in add_wait_queue stuff */
add_wait_queue(&serial->write_wait, &wait); add_wait_queue(&serial->write_wait, &wait);
set_current_state (TASK_INTERRUPTIBLE); set_current_state (TASK_INTERRUPTIBLE);
...@@ -418,7 +423,8 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb) ...@@ -418,7 +423,8 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
if (urb->status) { if (urb->status) {
err("nonzero read bulk status received: %d", urb->status); /* This will happen at close every time so it is a dbg not an err */
dbg("nonzero read bulk status received: %d", urb->status);
return; return;
} }
...@@ -585,59 +591,9 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * ...@@ -585,59 +591,9 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
return; return;
} /* ftdi_sio_set_termios */ } /* ftdi_sio_set_termios */
/*
* set_termios - Taken from tty_ioctl.c with some mods
*
* Used to correctly handle various options (ie TERMIOS_FLUSH etc)
*
*/
/*
* Internal flag options for termios setting behavior
*/
#define TERMIOS_FLUSH 1
#define TERMIOS_WAIT 2
#define TERMIOS_TERMIO 4
/*
* set_termios - assumes old_termios is in kernel space not user space
* sets current to port->tty->termios, might check diffs against old_termios one day
*/
static int set_termios(struct usb_serial_port *port, struct termios *old_termios, int opt)
{ /* set_termios */
struct tty_struct *tty = port->tty;
int retval;
#ifdef NOT_IMPLEMENTED_YET
retval = tty_check_change(tty);
if (retval)
return retval;
#endif
if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
if (opt & TERMIOS_WAIT) {
tty_wait_until_sent(tty, 0);
if (signal_pending(current))
return -EINTR;
}
/* remember port->tty->termios has the new settings */
ftdi_sio_set_termios(port, old_termios);
return 0;
} /* set_termios */
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct tty_struct *tty = port->tty;
struct termios old_termios;
__u16 urb_value=0; /* Will hold the new flags */ __u16 urb_value=0; /* Will hold the new flags */
char buf[1]; char buf[1];
int ret, mask; int ret, mask;
...@@ -746,50 +702,20 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns ...@@ -746,50 +702,20 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
} }
break; break;
/* Code for the following is based on code from tty_ioctl.c */ /*
case TCGETS: * I had originally implemented TCSET{A,S}{,F,W} and
if (kernel_termios_to_user_termios((struct termios *)arg, tty->termios)) { * TCGET{A,S} here separately, however when testing I
return -EFAULT; * found that the higher layers actually do the termios
} else { * conversions themselves and pass the call onto
return 0; * ftdi_sio_set_termios.
} *
case TCSETSF: */
memcpy(&old_termios, tty->termios, sizeof (struct termios));
if ((ret = user_termios_to_kernel_termios(tty->termios,
(struct termios *)arg)))
return -EFAULT;
return set_termios(port, &old_termios, TERMIOS_FLUSH);
case TCSETSW:
memcpy(&old_termios, tty->termios, sizeof (struct termios));
if ((ret = user_termios_to_kernel_termios(tty->termios,
(struct termios *)arg)))
return -EFAULT;
return set_termios(port, &old_termios, TERMIOS_WAIT);
case TCSETS:
memcpy(&old_termios, tty->termios, sizeof (struct termios));
if ((ret = user_termios_to_kernel_termios(tty->termios,
(struct termios *)arg)))
return -EFAULT;
return set_termios(port, &old_termios, 0);
#ifdef NOT_COMPLETED_YET_NEED_TO_CONVERT_TERMIO_TO_TERMIOS
/* the 'A' flavours work on termio not termios */
case TCGETA:
if (kernel_termios_to_user_termio((struct termios *)arg, tty->termios)) {
return -EFAULT;
} else {
return 0;
}
break;
case TCSETAF:
return set_termios(port, arg, TERMIOS_FLUSH | TERMIOS_TERMIO);
case TCSETAW:
return set_termios(port, arg, TERMIOS_WAIT | TERMIOS_TERMIO);
case TCSETA:
return set_termios(port, arg, TERMIOS_TERMIO);
#endif
default: default:
err("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd); /* This is not an error - turns out the higher layers will do
* some ioctls itself (see comment above)
*/
dbg("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd);
return(-ENOIOCTLCMD); return(-ENOIOCTLCMD);
break; break;
} }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
struct usb_serial_port { struct usb_serial_port {
int magic; int magic;
struct usb_serial *serial; /* pointer back to the owner of this port */ struct usb_serial *serial; /* pointer back to the owner of this port */
struct tty_struct * tty; /* the coresponding tty for this device */ struct tty_struct * tty; /* the coresponding tty for this port */
unsigned char minor; unsigned char minor;
unsigned char number; unsigned char number;
char active; /* someone has this device open */ char active; /* someone has this device open */
...@@ -56,8 +56,9 @@ struct usb_serial_port { ...@@ -56,8 +56,9 @@ struct usb_serial_port {
struct usb_serial { struct usb_serial {
int magic; int magic;
struct usb_device * dev; struct usb_device * dev;
struct usb_serial_device_type * type; struct usb_serial_device_type * type; /* the type of usb serial device this is */
unsigned char minor; struct tty_driver * tty_driver; /* the tty_driver for this device */
unsigned char minor; /* the starting minor number for this device */
unsigned char num_ports; /* the number of ports this device has */ unsigned char num_ports; /* the number of ports this device has */
char num_interrupt_in; /* number of interrupt in endpoints we have */ char num_interrupt_in; /* number of interrupt in endpoints we have */
char num_bulk_in; /* number of bulk in endpoints we have */ char num_bulk_in; /* number of bulk in endpoints we have */
......
...@@ -14,6 +14,11 @@ ...@@ -14,6 +14,11 @@
* *
* See Documentation/usb/usb-serial.txt for more information on using this driver * See Documentation/usb/usb-serial.txt for more information on using this driver
* *
* (04/03/2000) gkh
* Changed the probe process to remove the module unload races.
* Changed where the tty layer gets initialized to have devfs work nicer.
* Added initial devfs support.
*
* (03/26/2000) gkh * (03/26/2000) gkh
* Split driver up into device specific pieces. * Split driver up into device specific pieces.
* *
...@@ -269,6 +274,10 @@ static struct usb_serial_device_type *usb_serial_devices[] = { ...@@ -269,6 +274,10 @@ static struct usb_serial_device_type *usb_serial_devices[] = {
}; };
/* variables needed for the tty_driver structure */
static char *driver_name = "usb";
static char *tty_driver_name = "usb/tty/%d";
/* local function prototypes */ /* local function prototypes */
static int serial_open (struct tty_struct *tty, struct file * filp); static int serial_open (struct tty_struct *tty, struct file * filp);
...@@ -924,6 +933,48 @@ static void generic_write_bulk_callback (struct urb *urb) ...@@ -924,6 +933,48 @@ static void generic_write_bulk_callback (struct urb *urb)
} }
static struct tty_driver * usb_serial_tty_driver_init (struct usb_serial *serial)
{
struct tty_driver *serial_tty_driver;
if (!(serial_tty_driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL))) {
err("Out of memory");
return NULL;
}
memset (serial_tty_driver, 0x00, sizeof(struct tty_driver));
/* initialize the entries that we don't want to be NULL */
serial_tty_driver->magic = TTY_DRIVER_MAGIC;
serial_tty_driver->driver_name = driver_name;
serial_tty_driver->name = tty_driver_name;
serial_tty_driver->major = SERIAL_TTY_MAJOR;
serial_tty_driver->minor_start = serial->minor;
serial_tty_driver->num = serial->num_ports;
serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
serial_tty_driver->flags = TTY_DRIVER_REAL_RAW;
serial_tty_driver->refcount = &serial_refcount;
serial_tty_driver->table = serial_tty;
serial_tty_driver->termios = serial_termios;
serial_tty_driver->termios_locked = serial_termios_locked;
serial_tty_driver->open = serial_open;
serial_tty_driver->close = serial_close;
serial_tty_driver->write = serial_write;
serial_tty_driver->write_room = serial_write_room;
serial_tty_driver->ioctl = serial_ioctl;
serial_tty_driver->set_termios = serial_set_termios;
serial_tty_driver->throttle = serial_throttle;
serial_tty_driver->unthrottle = serial_unthrottle;
serial_tty_driver->break_ctl = serial_break;
serial_tty_driver->chars_in_buffer = serial_chars_in_buffer;
serial_tty_driver->init_termios = tty_std_termios;
serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
return serial_tty_driver;
}
static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
{ {
struct usb_serial *serial = NULL; struct usb_serial *serial = NULL;
...@@ -1000,6 +1051,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) ...@@ -1000,6 +1051,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
(bulk_in_pipe & type->needs_bulk_in) && (bulk_in_pipe & type->needs_bulk_in) &&
(bulk_out_pipe & type->needs_bulk_out)) { (bulk_out_pipe & type->needs_bulk_out)) {
/* found all that we need */ /* found all that we need */
MOD_INC_USE_COUNT;
info("%s converter detected", type->name); info("%s converter detected", type->name);
#ifdef CONFIG_USB_SERIAL_GENERIC #ifdef CONFIG_USB_SERIAL_GENERIC
...@@ -1012,6 +1064,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) ...@@ -1012,6 +1064,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
serial = get_free_serial (num_ports, &minor); serial = get_free_serial (num_ports, &minor);
if (serial == NULL) { if (serial == NULL) {
err("No more free serial devices"); err("No more free serial devices");
MOD_DEC_USE_COUNT;
return NULL; return NULL;
} }
...@@ -1023,6 +1076,18 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) ...@@ -1023,6 +1076,18 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
serial->num_bulk_out = num_bulk_out; serial->num_bulk_out = num_bulk_out;
serial->num_interrupt_in = num_interrupt_in; serial->num_interrupt_in = num_interrupt_in;
/* initialize a tty_driver for this device */
serial->tty_driver = usb_serial_tty_driver_init (serial);
if (serial->tty_driver == NULL) {
err("Can't create a tty_serial_driver");
goto probe_error;
}
if (tty_register_driver (serial->tty_driver)) {
err("failed to register tty driver");
goto probe_error;
}
/* collect interrupt_in endpoints now, because /* collect interrupt_in endpoints now, because
the keyspan_pda startup function needs the keyspan_pda startup function needs
to know about them */ to know about them */
...@@ -1040,8 +1105,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) ...@@ -1040,8 +1105,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
/* if this device type has a startup function, call it */ /* if this device type has a startup function, call it */
if (type->startup) { if (type->startup) {
if (type->startup (serial)) { if (type->startup (serial)) {
return_serial (serial); goto probe_error;
return NULL;
} }
} }
...@@ -1114,8 +1178,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) ...@@ -1114,8 +1178,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i); info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
} }
MOD_INC_USE_COUNT;
return serial; return serial;
} else { } else {
info("descriptors matched, but endpoints did not"); info("descriptors matched, but endpoints did not");
...@@ -1153,8 +1215,16 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) ...@@ -1153,8 +1215,16 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
/* return the minor range that this device had */ /* return the minor range that this device had */
return_serial (serial); return_serial (serial);
/* if this device has a tty_driver, then unregister it and free it */
if (serial->tty_driver) {
tty_unregister_driver (serial->tty_driver);
kfree (serial->tty_driver);
serial->tty_driver = NULL;
}
/* free up any memory that we allocated */ /* free up any memory that we allocated */
kfree (serial); kfree (serial);
MOD_DEC_USE_COUNT;
} }
return NULL; return NULL;
} }
...@@ -1205,6 +1275,12 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) ...@@ -1205,6 +1275,12 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
/* return the minor range that this device had */ /* return the minor range that this device had */
return_serial (serial); return_serial (serial);
/* if this device has a tty_driver, then unregister it and free it */
if (serial->tty_driver) {
tty_unregister_driver (serial->tty_driver);
kfree (serial->tty_driver);
serial->tty_driver = NULL;
}
/* free up any memory that we allocated */ /* free up any memory that we allocated */
kfree (serial); kfree (serial);
...@@ -1216,46 +1292,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) ...@@ -1216,46 +1292,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
} }
static struct tty_driver serial_tty_driver = {
magic: TTY_DRIVER_MAGIC,
driver_name: "usb",
name: "ttyUSB%d",
major: SERIAL_TTY_MAJOR,
minor_start: 0,
num: SERIAL_TTY_MINORS,
type: TTY_DRIVER_TYPE_SERIAL,
subtype: SERIAL_TYPE_NORMAL,
flags: TTY_DRIVER_REAL_RAW,
refcount: &serial_refcount,
table: serial_tty,
proc_entry: NULL,
other: NULL,
termios: serial_termios,
termios_locked: serial_termios_locked,
open: serial_open,
close: serial_close,
write: serial_write,
put_char: NULL,
flush_chars: NULL,
write_room: serial_write_room,
ioctl: serial_ioctl,
set_termios: serial_set_termios,
set_ldisc: NULL,
throttle: serial_throttle,
unthrottle: serial_unthrottle,
stop: NULL,
start: NULL,
hangup: NULL,
break_ctl: serial_break,
wait_until_sent: NULL,
send_xchar: NULL,
read_proc: NULL,
chars_in_buffer: serial_chars_in_buffer,
flush_buffer: NULL
};
int usb_serial_init(void) int usb_serial_init(void)
{ {
int i; int i;
...@@ -1265,17 +1301,8 @@ int usb_serial_init(void) ...@@ -1265,17 +1301,8 @@ int usb_serial_init(void)
serial_table[i] = NULL; serial_table[i] = NULL;
} }
/* register the tty driver */
serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&serial_tty_driver)) {
err("failed to register tty driver");
return -EPERM;
}
/* register the USB driver */ /* register the USB driver */
if (usb_register(&usb_serial_driver) < 0) { if (usb_register(&usb_serial_driver) < 0) {
tty_unregister_driver(&serial_tty_driver);
return -1; return -1;
} }
...@@ -1286,7 +1313,6 @@ int usb_serial_init(void) ...@@ -1286,7 +1313,6 @@ int usb_serial_init(void)
void usb_serial_exit(void) void usb_serial_exit(void)
{ {
tty_unregister_driver(&serial_tty_driver);
usb_deregister(&usb_serial_driver); usb_deregister(&usb_serial_driver);
} }
......
...@@ -448,7 +448,7 @@ static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb) ...@@ -448,7 +448,7 @@ static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
if (!urbp->fsbr) { if (!urbp->fsbr) {
urbp->fsbr = 1; urbp->fsbr = 1;
if (!uhci->fsbr++) if (!uhci->fsbr++)
uhci->skel_term_td.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH; uhci->skel_term_qh.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
} }
spin_unlock_irqrestore(&uhci->framelist_lock, flags); spin_unlock_irqrestore(&uhci->framelist_lock, flags);
...@@ -467,7 +467,7 @@ static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb) ...@@ -467,7 +467,7 @@ static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
if (urbp->fsbr) { if (urbp->fsbr) {
urbp->fsbr = 0; urbp->fsbr = 0;
if (!--uhci->fsbr) if (!--uhci->fsbr)
uhci->skel_term_td.link = UHCI_PTR_TERM; uhci->skel_term_qh.link = UHCI_PTR_TERM;
} }
spin_unlock_irqrestore(&uhci->framelist_lock, flags); spin_unlock_irqrestore(&uhci->framelist_lock, flags);
...@@ -712,6 +712,10 @@ static int usb_control_retrigger_status(urb_t *urb) ...@@ -712,6 +712,10 @@ static int usb_control_retrigger_status(urb_t *urb)
urbp->short_control_packet = 1; urbp->short_control_packet = 1;
/* Create a new QH to avoid pointer overwriting problems */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = uhci_alloc_qh(urb->dev);
/* Delete all of the TD's except for the status TD at the end */ /* Delete all of the TD's except for the status TD at the end */
td = urbp->list.begin; td = urbp->list.begin;
while (td && td->list.next) { while (td && td->list.next) {
...@@ -726,10 +730,6 @@ static int usb_control_retrigger_status(urb_t *urb) ...@@ -726,10 +730,6 @@ static int usb_control_retrigger_status(urb_t *urb)
td = nexttd; td = nexttd;
} }
/* Create a new QH to avoid pointer overwriting problems */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = uhci_alloc_qh(urb->dev);
if (!urbp->qh) if (!urbp->qh)
return -ENOMEM; return -ENOMEM;
...@@ -1403,7 +1403,7 @@ static int rh_init_int_timer(urb_t *urb); ...@@ -1403,7 +1403,7 @@ static int rh_init_int_timer(urb_t *urb);
static void rh_int_timer_do(unsigned long ptr) static void rh_int_timer_do(unsigned long ptr)
{ {
urb_t *urb = (urb_t *)ptr, *u; struct urb *urb = (struct urb *)ptr;
struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv; struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
struct list_head *tmp, *head = &uhci->urb_list; struct list_head *tmp, *head = &uhci->urb_list;
struct urb_priv *urbp; struct urb_priv *urbp;
...@@ -1422,15 +1422,22 @@ static void rh_int_timer_do(unsigned long ptr) ...@@ -1422,15 +1422,22 @@ static void rh_int_timer_do(unsigned long ptr)
nested_lock(&uhci->urblist_lock, flags); nested_lock(&uhci->urblist_lock, flags);
tmp = head->next; tmp = head->next;
while (tmp != head) { while (tmp != head) {
u = list_entry(tmp, urb_t, urb_list); struct urb *u = list_entry(tmp, urb_t, urb_list);
tmp = tmp->next;
urbp = (struct urb_priv *)u->hcpriv; urbp = (struct urb_priv *)u->hcpriv;
if (urbp) { if (urbp) {
if (urbp->fsbr && time_after(jiffies, urbp->inserttime + IDLE_TIMEOUT)) /* Check if the FSBR timed out */
if (urbp->fsbr && time_after(urbp->inserttime + IDLE_TIMEOUT, jiffies))
uhci_dec_fsbr(uhci, u); uhci_dec_fsbr(uhci, u);
}
tmp = tmp->next; /* Check if the URB timed out */
if (u->timeout && time_after(u->timeout, jiffies)) {
u->transfer_flags |= USB_ASYNC_UNLINK;
uhci_unlink_urb(u);
}
}
} }
nested_unlock(&uhci->urblist_lock, flags); nested_unlock(&uhci->urblist_lock, flags);
......
This diff is collapsed.
This diff is collapsed.
...@@ -129,8 +129,8 @@ static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *seri ...@@ -129,8 +129,8 @@ static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *seri
} }
/* Flag definitions */ /* Flag definitions */
#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */ #define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */
#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */ #define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */
#define US_FL_MODE_XLATE 0x00000004 /* translate _6 to _10 comands for #define US_FL_MODE_XLATE 0x00000004 /* translate _6 to _10 comands for
Win/MacOS compatibility */ Win/MacOS compatibility */
#define US_FL_CBI_AS_CB 0x00000008 /* treat a CBI dev as a CB dev */
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Randy Dunlap * (C) Copyright 1999 Randy Dunlap
* *
* $Id: usb-uhci.c,v 1.222 2000/03/13 21:18:02 fliegl Exp $ * $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
/* This enables an extra UHCI slab for memory debugging */ /* This enables an extra UHCI slab for memory debugging */
#define DEBUG_SLAB #define DEBUG_SLAB
#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__
#include <linux/usb.h> #include <linux/usb.h>
#include "usb-uhci.h" #include "usb-uhci.h"
#include "usb-uhci-debug.h" #include "usb-uhci-debug.h"
...@@ -116,6 +118,26 @@ void clean_descs(uhci_t *s, int force) ...@@ -116,6 +118,26 @@ void clean_descs(uhci_t *s, int force)
} }
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
_static void uhci_switch_timer_int(uhci_t *s)
{
if (!list_empty(&s->urb_unlinked)) {
s->td1ms->hw.td.status |= TD_CTRL_IOC;
}
else {
s->td1ms->hw.td.status &= ~TD_CTRL_IOC;
}
if (s->timeout_urbs) {
s->td32ms->hw.td.status |= TD_CTRL_IOC;
}
else {
s->td32ms->hw.td.status &= ~TD_CTRL_IOC;
}
wmb();
}
/*-------------------------------------------------------------------*/
#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
_static void enable_desc_loop(uhci_t *s, urb_t *urb) _static void enable_desc_loop(uhci_t *s, urb_t *urb)
{ {
...@@ -162,6 +184,9 @@ _static void queue_urb_unlocked (uhci_t *s, urb_t *urb) ...@@ -162,6 +184,9 @@ _static void queue_urb_unlocked (uhci_t *s, urb_t *urb)
#endif #endif
((urb_priv_t*)urb->hcpriv)->started=jiffies; ((urb_priv_t*)urb->hcpriv)->started=jiffies;
list_add (p, &s->urb_list); list_add (p, &s->urb_list);
if (urb->timeout)
s->timeout_urbs++;
uhci_switch_timer_int(s);
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
_static void queue_urb (uhci_t *s, urb_t *urb) _static void queue_urb (uhci_t *s, urb_t *urb)
...@@ -185,6 +210,9 @@ _static void dequeue_urb (uhci_t *s, urb_t *urb) ...@@ -185,6 +210,9 @@ _static void dequeue_urb (uhci_t *s, urb_t *urb)
#endif #endif
list_del (&urb->urb_list); list_del (&urb->urb_list);
if (urb->timeout && s->timeout_urbs)
s->timeout_urbs--;
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
_static int alloc_td (uhci_desc_t ** new, int flags) _static int alloc_td (uhci_desc_t ** new, int flags)
...@@ -439,6 +467,13 @@ _static void cleanup_skel (uhci_t *s) ...@@ -439,6 +467,13 @@ _static void cleanup_skel (uhci_t *s)
clean_descs(s,1); clean_descs(s,1);
if (s->td32ms) {
unlink_td(s,s->td32ms,1);
delete_desc(s->td32ms);
}
for (n = 0; n < 8; n++) { for (n = 0; n < 8; n++) {
td = s->int_chain[n]; td = s->int_chain[n];
clean_td_chain (td); clean_td_chain (td);
...@@ -531,8 +566,9 @@ _static int init_skel (uhci_t *s) ...@@ -531,8 +566,9 @@ _static int init_skel (uhci_t *s)
if (ret) if (ret)
goto init_skel_cleanup; goto init_skel_cleanup;
fill_td (td, TD_CTRL_IOC, 0, 0); // generate 1ms interrupt fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
insert_td (s, qh, td, 0); insert_td (s, qh, td, 0);
s->td1ms=td;
dbg("allocating qh: bulk_chain"); dbg("allocating qh: bulk_chain");
ret = alloc_qh (&qh); ret = alloc_qh (&qh);
...@@ -597,6 +633,16 @@ _static int init_skel (uhci_t *s) ...@@ -597,6 +633,16 @@ _static int init_skel (uhci_t *s)
((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]); ((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
} }
ret = alloc_td (&td, 0);
if (ret)
goto init_skel_cleanup;
fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt
s->td32ms=td;
insert_td_horizontal (s, s->int_chain[5], td);
mb(); mb();
//uhci_show_queue(s->control_chain); //uhci_show_queue(s->control_chain);
dbg("init_skel exit"); dbg("init_skel exit");
...@@ -995,6 +1041,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) ...@@ -995,6 +1041,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
if (urb->status == -EINPROGRESS) { if (urb->status == -EINPROGRESS) {
// URB probably still in work // URB probably still in work
dequeue_urb (s, urb); dequeue_urb (s, urb);
uhci_switch_timer_int(s);
s->unlink_urb_done=1; s->unlink_urb_done=1;
spin_unlock_irqrestore (&s->urb_list_lock, flags); spin_unlock_irqrestore (&s->urb_list_lock, flags);
...@@ -1125,9 +1172,11 @@ _static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb) ...@@ -1125,9 +1172,11 @@ _static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb)
if (urb->status == -EINPROGRESS) { if (urb->status == -EINPROGRESS) {
((urb_priv_t*)urb->hcpriv)->started = ~0; ((urb_priv_t*)urb->hcpriv)->started = ~0;
dequeue_urb (s, urb); dequeue_urb (s, urb);
list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb
uhci_switch_timer_int(s);
s->unlink_urb_done = 1; s->unlink_urb_done = 1;
urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" urb->status = -ECONNABORTED; // mark urb as "waiting to be killed"
...@@ -1495,7 +1544,7 @@ _static int uhci_submit_urb (urb_t *urb) ...@@ -1495,7 +1544,7 @@ _static int uhci_submit_urb (urb_t *urb)
(!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) { (!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) {
spin_unlock_irqrestore (&s->urb_list_lock, flags); spin_unlock_irqrestore (&s->urb_list_lock, flags);
usb_dec_dev_use (urb->dev); usb_dec_dev_use (urb->dev);
err("ENXIO1 %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb); err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb);
return -ENXIO; // urb already queued return -ENXIO; // urb already queued
} }
} }
...@@ -1599,6 +1648,7 @@ _static void uhci_check_timeouts(uhci_t *s) ...@@ -1599,6 +1648,7 @@ _static void uhci_check_timeouts(uhci_t *s)
#endif #endif
} }
s->timeout_check=jiffies;
} }
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
...@@ -1922,7 +1972,7 @@ _static int rh_submit_urb (urb_t *urb) ...@@ -1922,7 +1972,7 @@ _static int rh_submit_urb (urb_t *urb)
OK (len); OK (len);
case (0x03): /* string descriptors */ case (0x03): /* string descriptors */
len = usb_root_hub_string (wValue & 0xff, len = usb_root_hub_string (wValue & 0xff,
uhci->io_addr, "UHCI", uhci->io_addr, "UHCI",
data, wLength); data, wLength);
if (len > 0) { if (len > 0) {
OK (min (leni, len)); OK (min (leni, len));
...@@ -2481,15 +2531,15 @@ _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs) ...@@ -2481,15 +2531,15 @@ _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
goto restart; goto restart;
} }
} }
if ((s->frame_counter & 63) == 0) if ((jiffies - s->timeout_check) > (HZ/30))
uhci_check_timeouts(s); uhci_check_timeouts(s);
clean_descs(s,0); clean_descs(s,0);
uhci_cleanup_unlink(s, 0); uhci_cleanup_unlink(s, 0);
uhci_switch_timer_int(s);
spin_unlock (&s->urb_list_lock); spin_unlock (&s->urb_list_lock);
s->frame_counter++;
outw (status, io_addr + USBSTS); outw (status, io_addr + USBSTS);
//dbg("uhci_interrupt: done"); //dbg("uhci_interrupt: done");
...@@ -2630,12 +2680,14 @@ _static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_add ...@@ -2630,12 +2680,14 @@ _static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_add
spin_lock_init (&s->qh_lock); spin_lock_init (&s->qh_lock);
spin_lock_init (&s->td_lock); spin_lock_init (&s->td_lock);
atomic_set(&s->avoid_bulk, 0); atomic_set(&s->avoid_bulk, 0);
s->timeout_urbs = 0;
s->irq = -1; s->irq = -1;
s->io_addr = io_addr; s->io_addr = io_addr;
s->io_size = io_size; s->io_size = io_size;
s->next = devs; //chain new uhci device into global list s->next = devs; //chain new uhci device into global list
s->frame_counter = 0; s->timeout_check = 0;
s->uhci_pci=dev;
bus = usb_alloc_bus (&uhci_device_operations); bus = usb_alloc_bus (&uhci_device_operations);
if (!bus) { if (!bus) {
kfree (s); kfree (s);
...@@ -2739,6 +2791,7 @@ _static int __init start_uhci (struct pci_dev *dev) ...@@ -2739,6 +2791,7 @@ _static int __init start_uhci (struct pci_dev *dev)
info("Intel USB controller: setting latency timer to %d", UHCI_LATENCY_TIMER); info("Intel USB controller: setting latency timer to %d", UHCI_LATENCY_TIMER);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, UHCI_LATENCY_TIMER); pci_write_config_byte(dev, PCI_LATENCY_TIMER, UHCI_LATENCY_TIMER);
} }
return alloc_uhci(dev, dev->irq, io_addr, io_size); return alloc_uhci(dev, dev->irq, io_addr, io_size);
} }
return -1; return -1;
......
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
#define __LINUX_UHCI_H #define __LINUX_UHCI_H
/* /*
$Id: usb-uhci.h,v 1.50 2000/03/13 21:18:04 fliegl Exp $ $Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $
*/ */
#define MODNAME "usb-uhci" #define MODNAME "usb-uhci"
#define VERSTR "$Revision: 1.50 $ time " __TIME__ " " __DATE__
#define UHCI_LATENCY_TIMER 0 #define UHCI_LATENCY_TIMER 0
static __inline__ void uhci_wait_ms(unsigned int ms) static __inline__ void uhci_wait_ms(unsigned int ms)
...@@ -202,6 +201,8 @@ typedef struct uhci { ...@@ -202,6 +201,8 @@ typedef struct uhci {
uhci_desc_t *control_chain; uhci_desc_t *control_chain;
uhci_desc_t *bulk_chain; uhci_desc_t *bulk_chain;
uhci_desc_t *chain_end; uhci_desc_t *chain_end;
uhci_desc_t *td1ms;
uhci_desc_t *td32ms;
struct list_head free_desc; struct list_head free_desc;
spinlock_t qh_lock; spinlock_t qh_lock;
spinlock_t td_lock; spinlock_t td_lock;
...@@ -209,7 +210,9 @@ typedef struct uhci { ...@@ -209,7 +210,9 @@ typedef struct uhci {
int loop_usage; // URBs using bandwidth reclamation int loop_usage; // URBs using bandwidth reclamation
struct list_head urb_unlinked; // list of all unlinked urbs struct list_head urb_unlinked; // list of all unlinked urbs
int frame_counter; long timeout_check;
int timeout_urbs;
struct pci_dev *uhci_pci;
} uhci_t, *puhci_t; } uhci_t, *puhci_t;
......
...@@ -71,7 +71,7 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -71,7 +71,7 @@ if [ "$CONFIG_NET" = "y" ]; then
dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET
dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
dep_bool ' Provide NFSv3 client support (EXPERIMENTAL)' CONFIG_NFS_V3 $CONFIG_NFS_FS dep_mbool ' Provide NFSv3 client support (EXPERIMENTAL)' CONFIG_NFS_V3 $CONFIG_NFS_FS
dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
...@@ -89,7 +89,7 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -89,7 +89,7 @@ if [ "$CONFIG_NET" = "y" ]; then
define_tristate CONFIG_LOCKD n define_tristate CONFIG_LOCKD n
fi fi
fi fi
if [ "$CONFIG_NFSD_V3" = "y" ]; then if [ "$CONFIG_NFSD_V3" = "y" -o "$CONFIG_NFS_V3" = "y" ]; then
define_bool CONFIG_LOCKD_V4 y define_bool CONFIG_LOCKD_V4 y
fi fi
......
...@@ -18,10 +18,10 @@ static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen) ...@@ -18,10 +18,10 @@ static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
return vfs_readlink(dentry, buffer, buflen, s); return vfs_readlink(dentry, buffer, buflen, s);
} }
static struct dentry *autofs_follow_link(struct dentry *dentry, struct dentry *base, struct vfsmount **mnt, unsigned flags) static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
return vfs_follow_link(dentry, base, mnt, flags, s); return vfs_follow_link(nd, s);
} }
struct inode_operations autofs_symlink_inode_operations = { struct inode_operations autofs_symlink_inode_operations = {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -2,7 +2,7 @@ struct proc_inode_info { ...@@ -2,7 +2,7 @@ struct proc_inode_info {
struct task_struct *task; struct task_struct *task;
int type; int type;
union { union {
struct dentry *(*proc_get_link)(struct inode *, struct vfsmount **); int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
int (*proc_read)(struct task_struct *task, char *page); int (*proc_read)(struct task_struct *task, char *page);
} op; } op;
struct file *file; struct file *file;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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