]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.37 2.3.37
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:29:52 +0000 (15:29 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:29:52 +0000 (15:29 -0500)
148 files changed:
CREDITS
Documentation/fb/clgenfb.txt
Documentation/networking/ip-sysctl.txt
Documentation/pci.txt
Documentation/proc_usb_info.txt [deleted file]
Documentation/usb/CREDITS [new file with mode: 0644]
Documentation/usb/URB.txt [new file with mode: 0644]
Documentation/usb/acm.txt [new file with mode: 0644]
Documentation/usb/dc2xx.txt [new file with mode: 0644]
Documentation/usb/error-codes.txt [new file with mode: 0644]
Documentation/usb/hid.txt [new file with mode: 0644]
Documentation/usb/ohci-hcd.txt [new file with mode: 0644]
Documentation/usb/ov511.txt [new file with mode: 0644]
Documentation/usb/proc_usb_info.txt [new file with mode: 0644]
Documentation/usb/scanner-hp-sane.txt [new file with mode: 0644]
Documentation/usb/scanner.txt [new file with mode: 0644]
Documentation/usb/uhci.txt [new file with mode: 0644]
Documentation/usb/usb-serial.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/sys_sio.c
arch/arm/kernel/bios32.c
arch/i386/boot/setup.S
arch/i386/config.in
arch/i386/kernel/acpi.c
arch/i386/kernel/apm.c
arch/i386/kernel/i386_ksyms.c
arch/i386/kernel/irq.c
arch/i386/kernel/pci-i386.c
arch/i386/kernel/pci-pc.c
arch/i386/kernel/pci-visws.c
arch/m68k/kernel/bios32.c
arch/mips/sni/pci.c
arch/ppc/kernel/chrp_pci.c
arch/ppc/kernel/pci.c
arch/ppc/kernel/pmac_pci.c
arch/ppc/kernel/prep_pci.c
arch/sparc/kernel/sys_sunos.c
arch/sparc64/kernel/sys_sunos32.c
drivers/acorn/block/fd1772.c
drivers/block/alim15x3.c
drivers/block/ataflop.c
drivers/block/floppy.c
drivers/block/ide-pci.c
drivers/block/loop.c
drivers/block/swim3.c
drivers/block/swim_iop.c
drivers/block/via82cxxx.c
drivers/char/agp/agpgart_fe.c
drivers/char/bttv.c
drivers/char/random.c
drivers/char/raw.c
drivers/char/serial.c
drivers/char/stradis.c
drivers/i2o/i2o_pci.c
drivers/macintosh/via-pmu.c
drivers/net/pcmcia/ray_cs.c
drivers/net/pcmcia/tulip_cb.c
drivers/parport/parport_pc.c
drivers/pci/compat.c
drivers/pci/helper.c
drivers/pci/pci.c
drivers/pci/pci.ids
drivers/pci/pcisyms.c
drivers/pci/proc.c
drivers/pci/setup.c
drivers/pcmcia/cardbus.c
drivers/pcmcia/yenta.c
drivers/pnp/isapnp.c
drivers/pnp/isapnp_proc.c
drivers/scsi/megaraid.c
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/esssolo1.c
drivers/sound/nm256_audio.c
drivers/sound/sonicvibes.c
drivers/usb/CREDITS [deleted file]
drivers/usb/README.URB [deleted file]
drivers/usb/README.acm [deleted file]
drivers/usb/README.dc2xx [deleted file]
drivers/usb/README.error-codes [deleted file]
drivers/usb/README.hid [deleted file]
drivers/usb/README.ohci_hcd [deleted file]
drivers/usb/README.ov511 [deleted file]
drivers/usb/README.scanner [deleted file]
drivers/usb/README.scanner_hp_sane [deleted file]
drivers/usb/README.serial [deleted file]
drivers/usb/README.uhci [deleted file]
drivers/usb/ohci-hcd.c
drivers/usb/ov511.c
drivers/usb/ov511.h
drivers/usb/usb_scsi.c
drivers/usb/usb_scsi_dt.c [deleted file]
drivers/video/aty128fb.c
drivers/video/atyfb.c
drivers/video/clgenfb.c
drivers/video/clgenfb.h
drivers/video/fbmem.c
drivers/video/imsttfb.c
drivers/video/matroxfb.c
drivers/video/offb.c
drivers/video/pm2fb.c
drivers/video/rivafb.c
drivers/video/tdfxfb.c
drivers/video/vesafb.c
drivers/video/vga.h
drivers/video/vga16fb.c
fs/block_dev.c
fs/devices.c
fs/fifo.c
fs/inode.c
fs/isofs/inode.c
fs/super.c
fs/udf/inode.c
fs/udf/lowlevel.c
fs/udf/super.c
fs/udf/udfdecl.h
include/asm-i386/semaphore.h
include/linux/acpi.h
include/linux/fs.h
include/linux/pci.h
include/linux/random.h
include/linux/rtnetlink.h
include/linux/sysctl.h
include/net/inetpeer.h [new file with mode: 0644]
include/net/ip.h
include/net/route.h
init/main.c
kernel/ksyms.c
mm/swapfile.c
net/ipv4/Config.in
net/ipv4/Makefile
net/ipv4/igmp.c
net/ipv4/inetpeer.c [new file with mode: 0644]
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_ipv4.c
net/ipv6/ip6_output.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/netsyms.c

diff --git a/CREDITS b/CREDITS
index 15cc92ad9b45016d847dc6cb7a418d497849fccf..c84cd45b1689dc6201072af5d6d7eafebb5fbe21 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -692,6 +692,9 @@ S: 120 Alley Way
 S: Mountain View, California 94040
 S: USA
 
+N: Jeff Garzik
+E: jgarzik@mandrakesoft.com
+
 N: Jacques Gelinas
 E: jacques@solucorp.qc.ca
 D: Author of the Umsdos file system
index 4e3de5e83120a85016b01c65ac86799211a0a2a1..a9c71ccfe5ddc56f5903f76421ae2a9a4adec368 100644 (file)
@@ -1,6 +1,6 @@
 
                Framebuffer driver for Cirrus Logic chipsets
-               Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+               Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
 
 
 
index 8def0e7fc2b747dcaeb192deeb40537fa7f46577..614cf43b75a8e1ffda02f6163733cf2567a6de15 100644 (file)
@@ -51,6 +51,36 @@ ipfrag_low_thresh - INTEGER
 ipfrag_time - INTEGER
        Time in seconds to keep an IP fragment in memory.       
 
+INET peer storage:
+
+inet_peer_threshold - INTEGER
+       The approximate size of the storage.  Starting from this threshold      
+       entries will be thrown aggressively.  This threshold also determines
+       entries' time-to-live and time intervals between garbage collection
+       passes.  More entries, less time-to-live, less GC interval.
+
+inet_peer_minttl - INTEGER
+       Minimum time-to-live of entries.  Should be enough to cover fragment
+       time-to-live on the reassembling side.  This minimum time-to-live  is
+       guaranteed if the pool size is less than inet_peer_threshold.
+       Measured in jiffies.
+
+inet_peer_maxttl - INTEGER
+       Maximum time-to-live of entries.  Unused entries will expire after
+       this period of time if there is no memory pressure on the pool (i.e.
+       when the number of entries in the pool is very small).
+       Measured in jiffies.
+
+inet_peer_gc_mintime - INTEGER
+       Minimum interval between garbage collection passes.  This interval is
+       in effect under high memory pressure on the pool.
+       Measured in jiffies.
+
+inet_peer_gc_maxtime - INTEGER
+       Minimum interval between garbage collection passes.  This interval is
+       in effect under low (or absent) memory pressure on the pool.
+       Measured in jiffies.
+
 TCP variables: 
 
 tcp_syn_retries - INTEGER
@@ -211,4 +241,4 @@ kuznet@ms2.inr.ac.ru
 Updated by:
 Andi Kleen
 ak@muc.de
-$Id: ip-sysctl.txt,v 1.9 1999/05/08 02:58:44 davem Exp $
+$Id: ip-sysctl.txt,v 1.10 2000/01/06 00:41:42 davem Exp $
index 7108532cb3697e35796cc685f9291561e27d41ea..e74477fd4a2e11f0210a37c6346ffd8e36aa785d 100644 (file)
@@ -35,8 +35,13 @@ pci_find_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
 VENDOR_ID or DEVICE_ID.  This allows searching for any device from a
 specific vendor, for example.
 
-   In case you want to do some complex matching, look at pci_devices -- it's
-a linked list of pci_dev structures for all PCI devices in the system.
+   In case you want to do some complex matching, you can walk the list of all
+known PCI devices:
+
+               struct pci_dev *dev;
+               pci_for_each_dev(dev) {
+                       ... do anything you want with dev ...
+               }
 
    The `struct pci_dev *' pointer serves as an identification of a PCI device
 and is passed to all other functions operating on PCI devices.
diff --git a/Documentation/proc_usb_info.txt b/Documentation/proc_usb_info.txt
deleted file mode 100644 (file)
index 8d1066a..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/proc/bus/usb filesystem output
-===============================
-(version 19991218)
-
-
-The /proc filesystem for USB devices generates
-/proc/bus/usb/drivers and /proc/bus/usb/devices.
-
-/proc/bus/usb/drivers just lists the registered drivers,
-one per line.  Not very interesting or pretty.
-
-In /proc/bus/usb/devices, each device's output has multiple
-lines (except for a root hub) of ASCII output.
-I made it ASCII instead of binary on purpose, so that someone
-can obtain some useful data from it without the use of an
-auxiliary program.  However, with an auxiliary program, the numbers
-in the first 4 columns of each "T:" line (topology info:
-Lev, Prnt, Port, Cnt) can be used to build a USB topology diagram.
-(I think.  I haven't proved this, but I have tested it with 3
-different topo/connections and it looked possible.)
-
-Each line is tagged with a one-character ID for that line:
-
-T = Topology (etc.)
-B = Bandwidth
-D = Device descriptor info.
-P = Product ID info. (from Device descriptor, but they won't fit
-    together on one line)
-S = String info
-C = Configuration descriptor info. (* = active configuration)
-I = Interface descriptor info.
-E = Endpoint descriptor info.
-
-=======================================================================
-
-/proc/bus/usb/devices output format:
-
-Legend:
-  d = decimal number (may have leading spaces or 0's)
-  x = hexadecimal number (may have leading spaces or 0's)
-  s = string
-
-
-Topology info:
-
-T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
-|   |      |      |       |       |      |        |       |__MaxChildren
-|   |      |      |       |       |      |        |__Device Speed in Mbps
-|   |      |      |       |       |      |__DeviceNumber
-|   |      |      |       |       |__Count of devices at this level
-|   |      |      |       |__Connector/Port on Parent for this device
-|   |      |      |__Parent DeviceNumber
-|   |      |__Level in topology for this bus
-|   |__Bus number
-|__Topology info tag
-
-
-Bandwidth info:
-B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
-|   |                       |         |__Number if isochronous requests
-|   |                       |__Number of interrupt requests
-|   |__Total Bandwidth allocated to this bus
-|__Bandwidth info tag
-
-
-Device descriptor info & Product ID info:
-
-D:  Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
-P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx
-
-where
-D:  Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
-|   |        |             |      |       |       |__NumberConfigurations
-|   |        |             |      |       |__MaxPacketSize of Default Endpoint
-|   |        |             |      |__DeviceProtocol
-|   |        |             |__DeviceSubClass
-|   |        |__DeviceClass
-|   |__Device USB version
-|__Device info tag #1
-
-where
-P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx
-|   |           |           |__Product revision number
-|   |           |__Product ID code
-|   |__Vendor ID code
-|__Device info tag #2
-
-
-String descriptor info:
-
-S:  Manufacturer=ssss
-|   |__Manufacturer of this device as read from the device.
-|__String info tag
-
-S:  Product=ssss
-|   |__Product description of this device as read from the device.
-|__String info tag
-
-
-Configuration descriptor info:
-
-C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
-|   |       |       |      |__MaxPower in mA
-|   |       |       |__Attributes
-|   |       |__ConfiguratioNumber
-|   |__NumberOfInterfaces
-|__Config info tag
-
-
-Interface descriptor info (can be multiple per Config):
-
-I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
-|   |      |      |       |             |      |       |__Driver name
-|   |      |      |       |             |      |__InterfaceProtocol
-|   |      |      |       |             |__InterfaceSubClass
-|   |      |      |       |__InterfaceClass
-|   |      |      |__NumberOfEndpoints
-|   |      |__AlternateSettingNumber
-|   |__InterfaceNumber
-|__Interface info tag
-
-
-Endpoint descriptor info (can be multiple per Interface):
-
-E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms
-E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms
-|   |        |            |         |__Interval
-|   |        |            |__EndpointMaxPacketSize
-|   |        |__Attributes(EndpointType)
-|   |__EndpointAddress(I=In,O=Out)
-|__Endpoint info tag
-
-=======================================================================
-
-
-If a user or script is interested only in Topology info, for
-example, use something like "grep ^T: /proc/bus/usb/devices"
-for only the Topology lines.  A command like
-"grep -i ^[tdp]: /proc/bus/usb/devices" can be used to list
-only the lines that begin with the characters in square brackets,
-where the valid characters are TDPCIE.  With a slightly more able
-script, it can display any selected lines (for example, only T, D,
-and P lines) and change their output format.  (The "procusb"
-Perl script is the beginning of this idea.  It will list only
-selected lines [selected from TDPCIE] or "All" lines from
-/proc/bus/usb/devices.)
-
-The Topology lines can be used to generate a graphic/pictorial
-of the USB devices on a system's root hub.  (See more below
-on how to do this.)
-
-The Interface lines can be used to determine what driver is
-being used for each device.
-
-The Configuration lines could be used to list maximum power
-(in milliamps) that a system's USB devices are using.
-For example, "grep ^C: /proc/bus/usb/devices".
-
-
-Here's an example, from a system which has a UHCI root hub,
-an external hub connected to the root hub, and a mouse and
-a serial converter connected to the external hub.
-
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
-B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
-D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
-P:  Vendor=0451 ProdID=1446 Rev= 1.00
-C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
-I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
-E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
-D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
-P:  Vendor=04b4 ProdID=0001 Rev= 0.00
-C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
-I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
-E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
-D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
-P:  Vendor=0565 ProdID=0001 Rev= 1.08
-S:  Manufacturer=Peracom Networks, Inc.
-S:  Product=Peracom USB to Serial Converter
-C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
-I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
-E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl= 16ms
-E:  Ad=01(O) Atr=02(Bulk) MxPS=  16 Ivl= 16ms
-E:  Ad=82(I) Atr=03(Int.) MxPS=   8 Ivl=  8ms
-
-
-Selecting only the "T:" and "I:" lines from this (for example, by using
-"procusb ti"), we have:
-
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
-I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
-I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
-I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
-
-
-Physically this looks like (or could be converted to):
-
-                      +------------------+
-                      |  PC/root_hub (12)|   Dev# = 1
-                      +------------------+   (nn) is Mbps.
-    Level 0           |  CN.0   |  CN.1  |   [CN = connector/port #]
-                      +------------------+
-                          /
-                         /
-            +-----------------------+
-  Level 1   | Dev#2: 4-port hub (12)|
-            +-----------------------+
-            |CN.0 |CN.1 |CN.2 |CN.3 |
-            +-----------------------+
-                \           \____________________
-                 \_____                          \
-                       \                          \
-               +--------------------+      +--------------------+
-  Level 2      | Dev# 3: mouse (1.5)|      | Dev# 4: serial (12)|
-               +--------------------+      +--------------------+
-
-
-
-Or, in a more tree-like structure (ports [Connectors] without
-connections could be omitted):
-
-PC:  Dev# 1, root hub, 2 ports, 12 Mbps
-|_ CN.0:  Dev# 2, hub, 4 ports, 12 Mbps
-     |_ CN.0:  Dev #3, mouse, 1.5 Mbps
-     |_ CN.1:
-     |_ CN.2:  Dev #4, serial, 12 Mbps
-     |_ CN.3:
-|_ CN.1:
-
-
-                         ### END ###
diff --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS
new file mode 100644 (file)
index 0000000..04e6760
--- /dev/null
@@ -0,0 +1,160 @@
+Credits for the Simple Linux USB Driver:
+
+The following people have contributed to this code (in alphabetical
+order by last name).  I'm sure this list should be longer, its
+difficult to maintain, add yourself with a patch if desired.
+
+  Alan Cox <alan@lxorguk.ukuu.org.uk>
+  Johannes Erdfelt <jerdfelt@sventech.com>
+  ham <ham@unsuave.com>
+  Bradley M Keryan <keryan@andrew.cmu.edu>
+  Paul Mackerras <paulus@cs.anu.edu.au>
+  David E. Nelson <dnelson@jump.net>
+  Vojtech Pavlik <vojtech@suse.cz>
+  Gregory P. Smith <greg@electricrain.com>
+  Linus Torvalds <torvalds@transmeta.com>
+  Roman Weissgaerber <weissg@vienna.at>
+  <Kazuki.Yasumatsu@fujixerox.co.jp>
+
+Special thanks to:
+
+  Inaky Perez Gonzalez <inaky@peloncho.fis.ucm.es> for starting the
+  Linux USB driver effort and writing much of the larger uusbd driver.
+  Much has been learned from that effort.
+
+  The NetBSD & FreeBSD USB developers.  For being on the Linux USB list
+  and offering suggestions and sharing implementation experiences.
+
+Additional thanks to the following companies and people for donations
+of hardware, support, time and development (this is from the original
+THANKS file in Inaky's driver):
+
+        The following corporations have helped us in the development
+        of Linux USB / UUSBD:
+
+       - 3Com GmbH for donating a ISDN Pro TA and supporting me
+         in technical questions and with test equipment. I'd never 
+         expect such a great help.
+
+        - USAR Systems provided us with one of their excellent USB
+          Evaluation Kits. It allows us to test the Linux-USB driver
+          for compilance with the latest USB specification. USAR
+          Systems recognized the importance of an up-to-date open
+          Operating System and supports this project with
+          Hardware. Thanks!.
+
+        - Thanks to Intel Corporation for their precious help.
+
+        - We teamed up with Cherry to make Linux the first OS with
+          built-in USB support. Cherry is one of the biggest keyboard
+          makers in the world.
+
+        - CMD Technology, Inc. sponsored us kindly donating a CSA-6700
+          PCI-to-USB Controller Board to test the OHCI implementation.
+
+        - Due to their support to us, Keytronic can be sure that they
+          will sell keyboards to some of the 3 million (at least)
+          Linux users.
+
+        - Many thanks to ing büro h doran [http://www.ibhdoran.com]!
+          It was almost imposible to get a PC backplate USB connector
+          for the motherboard here at Europe (mine, home-made, was
+          quite lowsy :). Now I know where to adquire nice USB stuff!
+
+        - Genius Germany donated a USB mouse to test the mouse boot
+          protocol. They've also donated a F-23 digital joystick and a
+          NetMouse Pro. Thanks! 
+
+        - AVM GmbH Berlin is supporting the development of the Linux
+          USB driver for the AVM ISDN Controller B1 USB. AVM is a
+          leading manufacturer for active and passive ISDN Controllers
+          and CAPI 2.0-based software. The active design of the AVM B1
+          is open for all OS platforms, including Linux.
+
+        - Thanks to Y-E Data, Inc. for donating their FlashBuster-U
+          USB Floppy Disk Drive, so we could test the bulk transfer
+          code.
+
+        - Many thanks to Logitech for contributing a three axis USB
+          mouse. 
+
+          Logitech designs, manufactures and markets
+          Human Interface Devices, having a long history and
+          experience in making devices such as keyboards, mice,
+          trackballs, cameras, loudspeakers and control devices for
+          gaming and professional use.
+
+          Being a recognized vendor and seller for all these devices,
+          they have donated USB mice, a joystick and a scanner, as a
+          way to acknowledge the importance of Linux and to allow
+          Logitech customers to enjoy support in their favorite
+          operating systems and all Linux users to use Logitech and
+          other USB hardware.
+
+          Logitech is official sponsor of the Linux Conference on
+          Feb. 11th 1999 in Vienna, where we'll will present the
+          current state of the Linux USB effort.
+
+        - CATC has provided means to uncover dark corners of the UHCI
+          inner workings with a USB Inspector.
+
+        - Thanks to Entrega for providing PCI to USB cards, hubs and
+          converter products for development. 
+
+
+        And thanks go to (hey! in no particular order :)
+
+        - Oren Tirosh <orenti@hishome.net>, for standing so patiently
+          all my doubts'bout USB and giving lots of cool ideas.
+
+        - Jochen Karrer <karrer@wpfd25.physik.uni-wuerzburg.de>, for
+          pointing out mortal bugs and giving advice.
+
+        - Edmund Humemberger <ed@atnet.at>, for it's great work on
+          public relationships and general management stuff for the
+          Linux-USB effort.
+
+        - Alberto Menegazzi <flash@flash.iol.it> is starting the
+          documentation for the UUSBD. Go for it!
+
+        - Ric Klaren <ia_ric@cs.utwente.nl> for doing nice
+          introductory documents (compiting with Alberto's :).
+
+        - Christian Groessler <cpg@aladdin.de>, for it's help on those
+          itchy bits ... :)
+
+        - Paul MacKerras for polishing OHCI and pushing me harder for
+          the iMac support, giving improvements and enhancements.
+
+        - Fernando Herrera <fherrera@eurielec.etsit.upm.es> has taken
+          charge of composing, maintaining and feeding the
+          long-awaited, unique and marvelous UUSBD FAQ! Tadaaaa!!!
+
+        - Rasca Gmelch <thron@gmx.de> has revived the raw driver and
+          pointed bugs, as well as started the uusbd-utils package.
+
+        - Peter Dettori <dettori@ozy.dec.com> is unconvering bugs like
+          crazy, as well as making cool suggestions, great :)
+
+        - All the Free Software and Linux community, the FSF & the GNU
+          project, the MIT X consortium, the TeX people ... everyone!
+          You know who you are!
+
+        - Big thanks to Richard Stallman for creating Emacs!
+
+        - The people at the linux-usb mailing list, for reading so
+          many messages :) Ok, no more kidding; for all your advices!
+
+        - All the people at the USB Implementors Forum for their
+          help and assistance.
+
+        - Nathan Myers <ncm@cantrip.org>, for his advice! (hope you
+          liked Cibeles' party).
+
+        - Linus Torvalds, for starting, developing and managing Linux.
+
+        - Mike Smith, Craig Keithley, Thierry Giron and Janet Schank
+          for convincing me USB Standard hubs are not that standard
+          and that's good to allow for vendor specific quirks on the
+          standard hub driver.
+
diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
new file mode 100644 (file)
index 0000000..67cb9e3
--- /dev/null
@@ -0,0 +1,196 @@
+1. Specification of the API
+
+1.1. Basic concept or 'What is an URB?'
+
+The basic idea of the new driver is message passing, the message itself is 
+called USB Request Block, or URB for short. 
+
+- An URB consists of all relevant information to execute any USB transaction 
+and deliver the data and status back. 
+
+- Execution of an URB is an inherently asynchronous operation, i.e. the 
+submit_urb(urb) call returns immediately after it has successfully queued 
+the requested action. 
+
+- Ongoing transfers for one URB (e.g. ISO) can simply be canceled with
+unlink_urb(urb) at any time. 
+
+- Each URB has a completion handler, which is called after the action
+has been successfully completed or canceled (INT transfers behave a bit
+different, see below). The URB also contains a context-pointer for free 
+usage and information passing to the completion handler.
+
+- URBs can be linked. After completing one URB, the next one can be
+automatically submitted. This is especially useful for ISO transfers:
+You only have read/write the data from/to the buffers in the completion 
+handler, the continous streaming itself is transparently done by the 
+URB-machinery.
+
+1.2. The URB structure
+
+typedef struct urb
+{
+// ignore, for host controller/URB machine internal use
+       void *hcpriv;                   // private data for host controller
+       struct list_head urb_list;      // list pointer to all active urbs 
+
+// This is used for urb linking
+       struct urb* next;               // pointer to next URB  
+       struct usb_device *dev;         // pointer to associated USB device
+
+// pipe is assembled by the various well known pipe-macros in usb.h
+       unsigned int pipe;              // pipe information
+
+// status after each completion
+       int status;                     // returned status
+       unsigned int transfer_flags;    // ASAP, SP_OK, EARLY_COMPLETE
+
+// for data stage (CTRL), BULK, INT and ISO
+       void *transfer_buffer;          // associated data buffer
+
+// expected length
+       int transfer_buffer_length;     // data buffer length
+       int actual_length;              // actual data buffer length    
+
+// setup stage for CTRL (always 8 bytes!)
+       unsigned char* setup_packet;    // setup packet (control only)
+       
+// with ASAP, start_frame is set to the determined frame
+       int start_frame;                // start frame (iso/irq)
+       int number_of_packets;          // # of packets (iso/int)
+       int interval;                   // polling interval (irq only)
+       int error_count;                // number of errors (iso only)
+       //
+       void *context;                  // context for completion routine
+       usb_complete_t complete;        // pointer to completion routine
+       //
+// specification of the requested data offsets and length for ISO
+       iso_packet_descriptor_t  iso_frame_desc[0];
+} urb_t, *purb_t;
+
+1.3. How to get an URB?
+
+URBs are allocated with the following call
+
+       purb_t alloc_urb(int isoframes)
+
+Return value is a pointer to the allocated URB, 0 if allocation failed.
+The parameter isoframes specifies the number of isochronous transfer frames
+you want to schedule. For CTRL/BULK/INT, use 0.
+
+To free an URB, use
+
+       void free_urb(purb_t purb)
+
+This call also may free internal (host controller specific) memory in the
+future.
+
+1.4. What has to be filled in?
+
+Depending on the type of transaction, there are some macros 
+(FILL_CONTROL_URB, FILL_BULK_URB, and FILL_INT_URB, defined in uhci.h)
+that simplify the URB creation. In general, all macros need the usb
+device pointer, the pipe (usual format), the transfer buffer, the 
+desired transfer length, the completion  handler, and its context. 
+Take a look at the uhci_control_msg-function that convert the old API 
+into an URB.
+
+Flags:
+For ISO there are two startup behaviors: Specified start_frame or ASAP.
+For ASAP set USB_ISO_ASAP in transfer_flags.
+
+If short packets should NOT be tolerated, set USB_DISABLE_SPD in 
+transfer_flags.
+
+Usually, (to reduce restart time) the completion handler is called
+AFTER the URB re-submission. You can get the other way by setting
+USB_URB_EARLY_COMPLETE in transfer_flags. This is implicite for
+INT transfers.
+
+1.5. How to submit an URB?
+
+Just call
+
+       int submit_urb(purb_t purb)
+
+It immediately returns, either with status 0 (request queued) or some
+error code, usually caused by the following:
+
+- Out of memory (-ENOMEM)
+- Wrong pipe handle (-ENXIO)
+- Unplugged device (-ENODEV)
+- Stalled endpoint (-EPIPE)
+- Too many queued ISO transfers (-EAGAIN)
+- Too many requested ISO frames (-EFBIG)
+- Invalid INT interval (-EINVAL)
+- More than one packet for INT (-EINVAL)
+
+After submission, urb->status is USB_ST_URB_PENDING.
+
+For isochronous endpoints, subsequent submitting of URBs to the same endpoint
+with the ASAP flag result in a seamless ISO streaming. Exception: The 
+execution cannot be scheduled later than 900 frames from the 'now'-time. 
+The same applies to INT transfers, but here the seamless continuation is 
+independent of the transfer flags (implicitely ASAP).
+
+1.6. How to cancel an already running URB?
+
+Call
+       int unlink_urb(purb_t purb)
+
+It removes the urb from the internal list and frees all allocated
+HW descriptors. The status is changed to USB_ST_URB_KILLED. After 
+unlink_urb() returns, you can safely free the URB with free_urb(urb)
+and all other possibly associated data (urb->context etc.)
+
+1.7. What about the completion handler?
+
+The completion handler is optional, but useful for fast data processing
+or wakeup of a sleeping process (as shown in the compatibility wrapper's 
+completion handler).
+
+The handler is of the following type:
+
+       typedef void (*usb_complete_t)(struct urb *);
+
+i.e. it gets just the URB that caused the completion call.
+In the completion handler, you should have a look at urb->status to
+detect any USB errors. Since the context parameter is included in the URB,
+you can pass information to the completion handler. 
+
+
+1.8. How to do isochronous (ISO) transfers?
+
+For ISO transfers you have to append the iso_packet_descriptor_t structure 
+to the URB for each frame you want to schedule. When using alloc_urb(n)
+(recommended), the isoframe-parameter n can be used to allocate the
+structures for n frames.
+
+For each entry you have to specify the data offset for this frame (base is
+transfer_buffer), and the length you want to write/expect to read.
+After completion, actual_length contains the actual transfered length and 
+status contains the resulting USB-status for the ISO transfer for this frame.
+It is allowed to specify a varying length from frame to frame (e.g. for
+audio synchronisation/adaptive transfer rates). You can also use the length 
+0 to omit one or more frames (striping).
+
+As can be concluded from above, the UHCI-driver does not care for continous
+data in case of short packet ISO reads! There's no fixup_isoc() like in the 
+old driver. There may be a common routine to do this in the future, but this 
+has nothing to do with the UHCI-driver!
+
+For scheduling you can choose your own start frame or ASAP. As written above,
+queuing more than one ISO frame with ASAP to the same device&endpoint result 
+in seamless ISO streaming. For continous streaming you have to use URB
+linking. 
+
+1.9. How to start interrupt (INT) transfers?
+
+INT transfers are currently implemented with 8 different queues for intervals 
+for 1, 2, 4,... 128ms. Only one TD is allocated for each interrupt. After
+calling the completion handler, the TD is recycled.
+With the submission of one URB, the interrupt is scheduled until it is
+canceled by unlink_urb.
+
+The submit_urb()-call modifies urb->interval to the rounded value.
+
diff --git a/Documentation/usb/acm.txt b/Documentation/usb/acm.txt
new file mode 100644 (file)
index 0000000..c978974
--- /dev/null
@@ -0,0 +1,94 @@
+The ACM driver works with modems and ISDN TAs that use the USB Abstract
+Control Model standard. 
+
+****************************
+Test it:
+Watch out, the driver is not stable and tested. Sync often, make backups,
+most importand: don't blame me...
+
+Create device files:
+mknod /dev/ttyACM0 c 166 0
+mknod /dev/ttyACM1 c 166 1
+mknod /dev/ttyACM2 c 166 2
+mknod /dev/ttyACM3 c 166 3
+Compile a kernel with support for your host controller (uhci only for now!)
+and support for ACM. Boot this kernel. If you connect your device to the
+USB bus you should see messages like the following:
+
+Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
+Jul 19 20:14:29 office kernel: Found 02:09
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office last message repeated 2 times
+Jul 19 20:14:29 office kernel: parsed = 39 len = 67
+Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping
+Jul 19 20:14:29 office kernel:    0 09
+Jul 19 20:14:29 office kernel:    1 02
+Jul 19 20:14:29 office kernel:    2 43
+Jul 19 20:14:29 office kernel:    3 00
+Jul 19 20:14:29 office kernel:    4 02
+Jul 19 20:14:29 office kernel:    5 02
+Jul 19 20:14:29 office kernel:    6 04
+Jul 19 20:14:29 office kernel:    7 60
+Jul 19 20:14:29 office kernel:    8 00
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 02:09
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office kernel: parsed = 67 len = 0
+Jul 19 20:14:29 office kernel: getstringtable
+Jul 19 20:14:29 office kernel: acm_probe
+Jul 19 20:14:29 office kernel: USB ACM found
+
+Watch out for the line:
+Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
+and the line:
+Jul 19 20:14:29 office kernel: USB ACM found
+These two lines show that the device was seen by the usb host controller and
+then recognized by the acm driver as a valid device.
+
+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 
+been able to do zmodem downloads to another pc. However downloads from one
+ISDN TA to another ISDN TA connected to the same PC didn't work. Don't
+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
+not finised with this. There might be a chance to get it working. However
+i'd like to know if your device is recognized as an ACM device. I'm also
+interested if the thing is stable or if it crashes.
+(should i say how it crases?)
+
+You should be able to add and remove devices from the bus. The driver will
+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 see but it's ok for now. (I hope ;-)
+
+Please report your experiences to me:
+fuerst@in.tum.de
+
+***************************
+I've tested it with:
+3Com ISDN Pro TA.
+
+It should work with (That means i know these devices conform to ACM):
+3Com Office Connect Modem
+3Com Sportster USB (I think that's what it's called)
+
+***************************
+Many thanks to 3Com which did not only support me with hardware but also
+with technical support in USB questions. They also allowed me to do tests in
+their lab. Great!
+
+***************************
+Known bugs:
+Flow control not tested (likely not to work)
+Some tty function calls not implemented (putchar, etc...)
+Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 )
+Not all mem is freed at close (need terminate irq in hcd)
+
+***************************
+Have fun,
+       Armin Fuerst
diff --git a/Documentation/usb/dc2xx.txt b/Documentation/usb/dc2xx.txt
new file mode 100644 (file)
index 0000000..25b0241
--- /dev/null
@@ -0,0 +1,110 @@
+13 November 1999
+david-b@pacbell.net
+
+This is an overview of how to use the "dc2xx" USB driver with certain
+digital still cameras from Kodak and other vendors.
+
+
+CAMERAS
+
+This driver will mostly be used with Kodak DC-2xx series digital still
+cameras, but it should be trivial to tell it about several non-Kodak
+USB-enabled cameras.
+
+You'll most likely want to hook it up to recent versions of "gPhoto"
+(www.gphoto.org), since version 0.4 and later know how to use it to talk
+to Kodak DC-240 and DC-280 cameras over USB.
+
+In addition the DC-260, DC-265, and DC-290 are currently recognized.
+However, like other cameras using the "Digita OS" (from www.flashpoint.com)
+there is no gPhoto support for this camera.  At this writing the best
+known support for these cameras is a Python script that supports image
+downloading from those cameras.  (See archives of the linux-usb mailing
+list.)  The DC-220 should also work with this driver, given information
+about the USB product IDs.  When it becomes available, the HP PhotoSmart
+C500 should also work ... it's another Digita OS camera with USB support.)
+
+It's likely that other digital still cameras can also use this USB driver,
+even if they're not from Kodak and don't use Digita.  The reason is that
+most currently known USB still camera protocols treat USB like a faster
+packet-carrying connection than a serial line, which is exactly how this
+driver looks to an application.
+
+
+USB HARDWARE
+
+This has been shown to work on x86 OHCI and UHCI (Intel) chipsets.  OHCI has
+been trouble free; not so with UHCI, which was first seen to be happy with
+2.3.24 kernels, and has not been as fast as OHCI.
+
+Note that in some cases changes in BIOS settings may be needed before
+your USB works.  At least one user has reported a need for SMP-related 
+settings as well.
+
+As yet, no reports have come from Linux users on non-Intel hardware.
+(You could color coordinate your iMac with a DC-240i ... :-)
+
+
+SETUP
+
+Configure in the DC2XX USB driver, and have it in your kernel.  Recently I
+compile it right in, but I've done it as a module in the past.
+
+Create a device, perhaps like this (both read and write):
+
+    # mknod -m 0666 /dev/kodak c 10 170
+
+That "170" is not formally assigned, and this command may change.  If you're
+using a non-Kodak camera, you may prefer another name.
+
+Don't plug in more than one compatible camera at this time.  One of them
+will be ignored, but I'd not be sure which one!
+
+
+SANITY TESTING
+
+First:  if you've got /proc support, make sure that the driver has hooked
+itself up correctly.
+
+    - you should see an entry in /proc/misc for the a Kodak DC-2xx
+      minor device number
+
+    - you should see an entry in /proc/bus/usb/drivers for "dc2xx",
+      if you also enabled USB /proc support.
+
+Second:  when you connect your camera to the computer, does it get recognized
+by the driver?
+
+    - if you've got /proc/bus/usb/devices, you should see an entry
+      something like this.  The "ProdID" may be different if you didn't
+      plug in a DC-240, but the "Driver=dc2xx" had better be there.
+
+       T:  Lev=01 Prnt=00 Port=00 Cnt=01 Dev#=  1 Spd=12  MxCh= 0
+       D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+       P:  Vendor=040a ProdID=0120 Rev= 1.08
+       C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=100mA
+       I:  If#= 0 Alt= 0 #EPs= 2 Cls=00(>ifc ) Sub=00 Prot=00 Driver=dc2xx
+       E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
+       E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
+
+    - if you don't have /proc support for USB, see if "dmesg" output
+      tells you that you plugged in your camera.
+
+       USB new device connect, assigned device number 1
+       Manufacturer: Eastman Kodak Company
+       Product: KODAK DC240 Zoom Digital Camera
+       USB Camera is connected
+       usbcore: dc2xx driver claimed interface c3a68600
+       ohci-control thread sleeping
+
+Third:  (optional) can you use gPhoto to talk to the camera?
+
+    - When you configure your camera, tell it to use "/dev/kodak" (or
+      whatever name you used).  Right now, gPhoto emits a diagnostic
+      message (non-GUI) saying that it since it didn't act like a TTY,
+      it's assuming it's got a USB connection.
+
+    - With the camera turned on, get the "camera summary".  It'll
+      talk to the camera -- and tell you you're using USB.
+
+If you got that far, you should be able to use everything fine.
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
new file mode 100644 (file)
index 0000000..8366613
--- /dev/null
@@ -0,0 +1,108 @@
+$Id: README.error-codes,v 1.1 1999/12/14 14:03:02 fliegl Exp $
+
+This is the documentation of (hopefully) all possible error codes (and
+their interpretation) that can be returned from the hostcontroller driver 
+and from usbcore.
+
+NOTE:
+The USB_ST_* codes are deferred and are only listed for compatibility, new
+software should use only -E* instead!
+
+
+
+**************************************************************************
+*                   Error codes returned by usb_submit_urb               *
+**************************************************************************
+
+Non-USB-specific:
+
+USB_ST_NOERROR
+0              URB submission went fine
+
+-ENOMEM                no memory for allocation of internal structures 
+
+USB-specific:
+
+-ENODEV                specified USB-device or bus doesn't exist
+
+-ENXIO         specified endpoint doesn't exist on the device
+
+USB_ST_URB_INVALID_ERROR
+-EINVAL                a) Invalid transfer type specified (or not supported)
+               b) Invalid interrupt interval (0<=n<256)
+               c) more than one interrupt packet requested
+
+-EAGAIN                a) specified ISO start frame too early
+               b) (using ISO-ASAP) too much scheduled for the future
+                  wait some time and try again.
+
+-EFBIG         too much ISO frames requested (currently uhci>900)
+
+-EPIPE         specified pipe-handle is already stalled
+
+-EMSGSIZE      endpoint message size is zero, do interface/alternate setting
+
+
+**************************************************************************
+*                   Error codes returned by in urb->status               *
+*                   or in iso_frame_desc[n].status (for ISO)             *
+**************************************************************************
+
+USB_ST_NOERROR
+0                      Transfer completed successfully
+
+USB_ST_URB_KILLED
+-ENOENT                        URB was canceled by unlink_urb
+
+USB_ST_URB_PENDING
+-EINPROGRESS           URB still pending, no results yet
+                       (actually no error until now;-)
+
+USB_ST_BITSTUFF
+USB_ST_INTERNALERROR
+-EPROTO                        a) bitstuff error
+                       b) unknown USB error 
+
+USB_ST_CRC
+-EILSEQ                        CRC mismatch
+
+-EPIPE                 a) babble detect
+                       b) endpoint stalled
+
+USB_ST_BUFFERUNDERRUN
+-ENOST                 buffer error
+
+USB_ST_NORESPONSE
+USB_ST_TIMEOUT
+-ETIMEDOUT             transfer timed out, NAK
+
+USB_ST_REMOVED 
+-ENODEV                        device was removed
+
+USB_ST_SHORT_PACKET
+-EREMOTEIO             short packet detected
+
+USB_ST_PARTIAL_ERROR
+-EXDEV                 ISO transfer only partially completed
+                       look at individual frame status for details
+
+USB_ST_URB_INVALID_ERROR
+-EINVAL                        ISO madness, if this happens: Log off and go home
+
+**************************************************************************
+*              Error codes returned by usbcore-functions                 *
+*           (expect also other submit and transfer status codes)         *
+**************************************************************************
+
+usb_register():
+USB_ST_NOTSUPPORTED
+-EINVAL                        error during registering new driver
+
+usb_terminate_bulk():
+USB_ST_REMOVED
+-ENODEV                        urb already removed
+
+usb_get_*/usb_set_*():
+                       All USB errors (submit/status) can occur
+
+
diff --git a/Documentation/usb/hid.txt b/Documentation/usb/hid.txt
new file mode 100644 (file)
index 0000000..3cd3373
--- /dev/null
@@ -0,0 +1,162 @@
+                          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.
diff --git a/Documentation/usb/ohci-hcd.txt b/Documentation/usb/ohci-hcd.txt
new file mode 100644 (file)
index 0000000..37a6372
--- /dev/null
@@ -0,0 +1,98 @@
+
+The OHCI HCD layer is a simple but nearly complete implementation of what the
+USB people would call a HCD  for the OHCI. 
+ (ISO comming soon, Bulk, INT u. CTRL transfers enabled)
+It is based on Linus Torvalds UHCI code and Gregory Smith OHCI fragments (0.03 source tree).
+The layer (functions) on top of it, is for interfacing to the alternate-usb device-drivers. 
+
+- Roman Weissgaerber <weissg@vienna.at>
+
+ * v4.0 1999/08/18 removed all dummy eds, unlink unused eds, code cleanup, bulk transfers 
+ * v2.1 1999/05/09 ep_addr correction, code cleanup
+ * v0.2.0 1999/05/04 
+ * everything has been moved into 2 files (ohci-hcd.c, ohci-hub-root.c and headers)
+ * virtual root hub is now an option, 
+ * memory allocation based on kmalloc and kfree now, simple Bus error handling, 
+ * INT and CTRL transfers enabled, Bulk included but disabled, ISO needs completion
+ * 
+ * from Linus Torvalds (uhci.c): APM (not tested); hub, usb_device, bus and related stuff
+ * from Greg Smith (ohci.c): better reset ohci-controller handling, hub
+ * 
+ * v0.1.0 1999/04/27 initial release
+to remove the module try:
+rmmod usb-ohci-hcd
+
+Features:
+- virtual root hub, all basic hub descriptors and commands (state: complete) 
+  this is an option now (v0.2.0)
+  #define  CONFIG_USB_OHCI_VROOTHUB includes the virtual hub code, (VROOTHUB)
+  default is with. 
+  (at the moment: the Virtual Root Hub is included automatically)
+  
+  files: ohci-root-hub.c, ohci-root-hub.h 
+
+- Endpoint Descriptor (ED) handling more static approach 
+ (EDs should be allocated in parallel to the SET CONFIGURATION command and they live
+ as long as the function (device) is alive or another configuration is choosen.
+ In the HCD layer the EDs has to be allocated manually either by calling a subroutine
+ or by sending a USB root hub vendor specific command to the virtual root hub.
+ At the alternate linux usb stack EDs will be added (allocated) at their first use.
+ ED will be unlinked from the HC chains if they are not bussy.
+ files: ohci-hcd.c ohci-hcd.h
+ routines:   (do not use for drivers, use the top layer alternate usb commands instead)
+ int usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr1, 
+            int interval, int load, f_handler handler, int ep_size, int speed)
+       adds an endpoint, (if the endpoint already exists some parameters will be updated)
+       
+ int usb_ohci_rm_ep( ) 
+       removes an endpoint and all pending TDs of that EP
+       
+  usb_ohci_rm_function( )
+       removes all Endpoints of a function (device)
+
+- Transfer Descriptors (TD): handling and allocation of TDs is transparent to the upper layers
+  The HCD takes care of TDs and EDs memory allocation whereas the upper layers (UBSD ...) has
+  to take care of buffer allocation.
+  files: ohci-hcd.c ohci-hcd.h 
+
+  There is one basic command for all types of bus transfers (INT, BULK, ISO, CTRL):
+  
+  int ohci_trans_req(struct ohci * ohci, hcd_ed, int ctrl_len, void  *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1)
+  
+  CTRL: ctrl, ctrl_len ... cmd buffer 
+        data, data_len ... data buffer (in or out)
+  INT, BULK:  ctrl = NULL, ctrl_len=0,
+               data, data_len ... data buffer (in or out)
+  ISO: tbd
+
+  There is no buffer reinsertion done by the internal HCD function. 
+  (The interface layer does this for a INT-pipe on request.)
+  If you want a transfer then you have to 
+  provide buffers by sending ohci_trans_req requests. As they are queued as TDs on an ED
+  you can send as many as you like. They should come back by the callback f_handler in
+  the same order (for each endpoint, not globally) If an error occurs all
+  queued transfers of an endpoint will return unsent. They will be marked with an error status.
+  
+  e.g double-buffering for int transfers:
+
+       ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0)
+       ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0)
+       
+  and when a data0 packet returns by the callback f_handler requeue it:
+       ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0)
+  and when a data1 packet returns by the callback f_handler requeue it:
+       ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0)
+       
+  lw0, lw1 are private fields for upper layers for ids or fine grained handlers.
+  The alternate usb uses them for dev_id and usb_device_irq handler.
+
+
+- Done list handling: returns the requests (callback f_handler in ED) and does 
+  some error handling, root-hub request dequeuing
+  (files: ohci-done-list.c in ohci-hcd.c now(v0.2.0))
+
+  
diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt
new file mode 100644 (file)
index 0000000..14163ae
--- /dev/null
@@ -0,0 +1,70 @@
+-------------------------------------------------------------------------------
+Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
+-------------------------------------------------------------------------------
+
+INTRODUCTION:
+
+This is a preliminary version of my OV511 Linux device driver. At the moment,
+it does not do much more than detect the chip and initialize it. As trivial
+as this sounds, it represents many hours of my work. Since OmniVision refused
+to release the full specs to me, I had to write code to probe out the register
+read/write commands. Some code is in place to allow a frame to be grabbed, but
+it is nowhere near complete.
+
+SUPPORTED CAMERAS:
+____________________________________________
+Manufacturer     | Model        | Custom ID 
+-----------------+--------------+-----------
+D-Link           | DSB-C300        | 3
+Creative Labs    | WebCam 3     | 21
+--------------------------------------------
+
+Any camera using the OV511 and the OV7610 CCD should work with this driver. The
+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
+in the kernel logs. If you have an unsupported camera, please send me the model,
+manufacturer and ID number and I will add it to the detection code. In the
+meantime, you can add to the code yourself in the function ov511_probe()
+
+WHAT YOU NEED:
+
+- If you want to help with the development, get the chip's specification docs at
+  http://www.ovt.com/omniusbp.html
+
+- A Video4Linux compatible frame grabber program (I recommend vidcat)
+  (see: http://www.exploits.org/v4l/ )
+  
+WHAT NEEDS TO BE DONE:
+
+In short, a lot. 
+
+UPDATE:
+Currently, the control messages are working fine ("vendor commands"; for
+reading and writing the OV511 registers.) The I2C bus commands for reading and
+writing the camera (OV7610) registers are implemented and working, with at least
+one person's camera. The isochronous-in endpoint for video data is finally
+producing data, but since ov511_parse_data() is not implemented you will not see
+a picture yet.
+
+Support for specific CCD's will have to be implemented as well (such as the
+OV7610.) 
+
+The rest of the work will involve implementing support for all the different
+resolutions, color depths, etc. Also, while support for the OV511's proprietary
+lossy compression is apparently not necessary (the code currently disables it,)
+it would be a nice addition as it improves performance quite a bit. OmniVision
+wouldn't tell me how the algorithm works, so we can't really work on that yet.
+Please kindly inform OmniVision that you would like them to release their
+specifications to the Linux community.
+
+HOW TO CONTACT ME:
+
+You can email me at mmcclelland@delphi.com . Please prefix the subject line
+with "OV511: " so that I am certain to notice your message.
+
+CREDITS:
+
+The code is based in no small part on the CPiA driver by Johannes Erdfelt,
+Randy Dunlap, and others. Big thanks to them for their pioneering work on that
+and the USB stack. Thanks to Bret Wallach for getting camera reg IO and ISOC
+working.
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
new file mode 100644 (file)
index 0000000..8d1066a
--- /dev/null
@@ -0,0 +1,237 @@
+/proc/bus/usb filesystem output
+===============================
+(version 19991218)
+
+
+The /proc filesystem for USB devices generates
+/proc/bus/usb/drivers and /proc/bus/usb/devices.
+
+/proc/bus/usb/drivers just lists the registered drivers,
+one per line.  Not very interesting or pretty.
+
+In /proc/bus/usb/devices, each device's output has multiple
+lines (except for a root hub) of ASCII output.
+I made it ASCII instead of binary on purpose, so that someone
+can obtain some useful data from it without the use of an
+auxiliary program.  However, with an auxiliary program, the numbers
+in the first 4 columns of each "T:" line (topology info:
+Lev, Prnt, Port, Cnt) can be used to build a USB topology diagram.
+(I think.  I haven't proved this, but I have tested it with 3
+different topo/connections and it looked possible.)
+
+Each line is tagged with a one-character ID for that line:
+
+T = Topology (etc.)
+B = Bandwidth
+D = Device descriptor info.
+P = Product ID info. (from Device descriptor, but they won't fit
+    together on one line)
+S = String info
+C = Configuration descriptor info. (* = active configuration)
+I = Interface descriptor info.
+E = Endpoint descriptor info.
+
+=======================================================================
+
+/proc/bus/usb/devices output format:
+
+Legend:
+  d = decimal number (may have leading spaces or 0's)
+  x = hexadecimal number (may have leading spaces or 0's)
+  s = string
+
+
+Topology info:
+
+T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
+|   |      |      |       |       |      |        |       |__MaxChildren
+|   |      |      |       |       |      |        |__Device Speed in Mbps
+|   |      |      |       |       |      |__DeviceNumber
+|   |      |      |       |       |__Count of devices at this level
+|   |      |      |       |__Connector/Port on Parent for this device
+|   |      |      |__Parent DeviceNumber
+|   |      |__Level in topology for this bus
+|   |__Bus number
+|__Topology info tag
+
+
+Bandwidth info:
+B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
+|   |                       |         |__Number if isochronous requests
+|   |                       |__Number of interrupt requests
+|   |__Total Bandwidth allocated to this bus
+|__Bandwidth info tag
+
+
+Device descriptor info & Product ID info:
+
+D:  Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
+P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx
+
+where
+D:  Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
+|   |        |             |      |       |       |__NumberConfigurations
+|   |        |             |      |       |__MaxPacketSize of Default Endpoint
+|   |        |             |      |__DeviceProtocol
+|   |        |             |__DeviceSubClass
+|   |        |__DeviceClass
+|   |__Device USB version
+|__Device info tag #1
+
+where
+P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx
+|   |           |           |__Product revision number
+|   |           |__Product ID code
+|   |__Vendor ID code
+|__Device info tag #2
+
+
+String descriptor info:
+
+S:  Manufacturer=ssss
+|   |__Manufacturer of this device as read from the device.
+|__String info tag
+
+S:  Product=ssss
+|   |__Product description of this device as read from the device.
+|__String info tag
+
+
+Configuration descriptor info:
+
+C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
+|   |       |       |      |__MaxPower in mA
+|   |       |       |__Attributes
+|   |       |__ConfiguratioNumber
+|   |__NumberOfInterfaces
+|__Config info tag
+
+
+Interface descriptor info (can be multiple per Config):
+
+I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
+|   |      |      |       |             |      |       |__Driver name
+|   |      |      |       |             |      |__InterfaceProtocol
+|   |      |      |       |             |__InterfaceSubClass
+|   |      |      |       |__InterfaceClass
+|   |      |      |__NumberOfEndpoints
+|   |      |__AlternateSettingNumber
+|   |__InterfaceNumber
+|__Interface info tag
+
+
+Endpoint descriptor info (can be multiple per Interface):
+
+E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms
+E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms
+|   |        |            |         |__Interval
+|   |        |            |__EndpointMaxPacketSize
+|   |        |__Attributes(EndpointType)
+|   |__EndpointAddress(I=In,O=Out)
+|__Endpoint info tag
+
+=======================================================================
+
+
+If a user or script is interested only in Topology info, for
+example, use something like "grep ^T: /proc/bus/usb/devices"
+for only the Topology lines.  A command like
+"grep -i ^[tdp]: /proc/bus/usb/devices" can be used to list
+only the lines that begin with the characters in square brackets,
+where the valid characters are TDPCIE.  With a slightly more able
+script, it can display any selected lines (for example, only T, D,
+and P lines) and change their output format.  (The "procusb"
+Perl script is the beginning of this idea.  It will list only
+selected lines [selected from TDPCIE] or "All" lines from
+/proc/bus/usb/devices.)
+
+The Topology lines can be used to generate a graphic/pictorial
+of the USB devices on a system's root hub.  (See more below
+on how to do this.)
+
+The Interface lines can be used to determine what driver is
+being used for each device.
+
+The Configuration lines could be used to list maximum power
+(in milliamps) that a system's USB devices are using.
+For example, "grep ^C: /proc/bus/usb/devices".
+
+
+Here's an example, from a system which has a UHCI root hub,
+an external hub connected to the root hub, and a mouse and
+a serial converter connected to the external hub.
+
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+P:  Vendor=0451 ProdID=1446 Rev= 1.00
+C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
+E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+P:  Vendor=04b4 ProdID=0001 Rev= 0.00
+C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
+E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+P:  Vendor=0565 ProdID=0001 Rev= 1.08
+S:  Manufacturer=Peracom Networks, Inc.
+S:  Product=Peracom USB to Serial Converter
+C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
+E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl= 16ms
+E:  Ad=01(O) Atr=02(Bulk) MxPS=  16 Ivl= 16ms
+E:  Ad=82(I) Atr=03(Int.) MxPS=   8 Ivl=  8ms
+
+
+Selecting only the "T:" and "I:" lines from this (for example, by using
+"procusb ti"), we have:
+
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
+
+
+Physically this looks like (or could be converted to):
+
+                      +------------------+
+                      |  PC/root_hub (12)|   Dev# = 1
+                      +------------------+   (nn) is Mbps.
+    Level 0           |  CN.0   |  CN.1  |   [CN = connector/port #]
+                      +------------------+
+                          /
+                         /
+            +-----------------------+
+  Level 1   | Dev#2: 4-port hub (12)|
+            +-----------------------+
+            |CN.0 |CN.1 |CN.2 |CN.3 |
+            +-----------------------+
+                \           \____________________
+                 \_____                          \
+                       \                          \
+               +--------------------+      +--------------------+
+  Level 2      | Dev# 3: mouse (1.5)|      | Dev# 4: serial (12)|
+               +--------------------+      +--------------------+
+
+
+
+Or, in a more tree-like structure (ports [Connectors] without
+connections could be omitted):
+
+PC:  Dev# 1, root hub, 2 ports, 12 Mbps
+|_ CN.0:  Dev# 2, hub, 4 ports, 12 Mbps
+     |_ CN.0:  Dev #3, mouse, 1.5 Mbps
+     |_ CN.1:
+     |_ CN.2:  Dev #4, serial, 12 Mbps
+     |_ CN.3:
+|_ CN.1:
+
+
+                         ### END ###
diff --git a/Documentation/usb/scanner-hp-sane.txt b/Documentation/usb/scanner-hp-sane.txt
new file mode 100644 (file)
index 0000000..220bbb2
--- /dev/null
@@ -0,0 +1,69 @@
+Oct. 19, 1999
+
+CHANGES
+
+- Ammended for Linux-2.3.22+
+
+
+INTRODUCTION
+
+This document will hopefully provide enough info on how to get SANE
+working with a Hewlett Packard USB capable scanner using the USB
+interface.  The majority of HP Scanners support the Scanner Control
+Language (SCL) which is both published by HP and supported by SANE.
+The only HP Scanner that I'm aware of that does not support SCL is the
+4200C.  All other HP scanners with USB interfaces should work (4100C,
+5200C, 6200C, and 6300C).  Of course as HP releases new scanners this
+information may change.
+
+
+REQUIREMENTS
+
+In order to get this running you'll need USB support in your kernel in
+addition to USB Scanner support.  Please refer to README.scanner
+for issues pertaining to Linux USB and USB Scanner support.
+
+An installed version of SANE which is available from
+http://www.mostang.com/sane/.  Testing has been performed using
+version SANE-1.0.1.  For instructions on building and installing SANE,
+refer to the various README files within the SANE distribution.
+
+
+OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW?
+
+NOTE: $INSTALL_DIR is the location where SANE was installed.  It may
+be /usr/local, /usr, /opt or somewhere else.  If you don't know, ask
+your system administrator.
+
+1) Make sure that you have the libsane-hp.* libraries under the
+$INSTALL_DIR/lib/sane/ directory.  If you don't, then the HP backend
+was either not compiled or installed properly.
+
+2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following
+files: dll.conf, hp.conf.
+
+  dll.conf:  Make sure that the 'hp' entry is present and uncommented.
+
+  hp.conf: This should contain two lines:
+
+    /dev/usbscanner
+    option connect-device
+
+3) You should now be able to use SANE (xscanimage or scanimage).
+
+Don't forget to read any relevant man pages regarding the usage of
+SANE.  If you have other entries uncommented in dll.conf, you may have
+to specify the device to (x)scanimage.  Again, `man` is your friend.
+The xscanimage (1) man page has info on how to get 'The Gimp' to work
+with xscanimage.  Note that Gimp support must be compiled into SANE
+for it work.  If you are dealing with a RedHat system, this means that
+you'll also need to install the gimp-devel rpm package.
+
+NOTE: The issues regarding core dumping by (x)scanimage have (or seem
+to be thus far) been resolved with version 0.2+ of the USB scanner
+driver which should be available in linux-2.3.23.  If you notice
+otherwise, please contact me.
+
+David /\/elson
+dnelson@jump.net
+http://www.jump.net/~dnelson
diff --git a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt
new file mode 100644 (file)
index 0000000..4b5de2b
--- /dev/null
@@ -0,0 +1,231 @@
+Oct 19, 1999
+
+CHANGES
+
+- Ammended for linux-2.3.22+
+- Appended hp_scan.c to end of this README
+- Removed most references to HP
+
+
+OVERVIEW
+
+This README will address issues regarding how to configure the kernel
+to access a USB scanner.  Although the driver was originally conceived
+for USB HP scanners, it's general enough so that it can be used with
+other scanners.  Also, one can now pass the USB Vendor and
+Product ID's using module parameters for unknown scanners.  Refer to
+the document README.scanner_hp_sane for guidance on how to configure
+SANE to use a USB HP Scanner.
+
+
+ADDITIONAL INFORMATION
+
+http://www.linux-usb.org/
+http://www.dynamine.net/linux-usb/HOWTO/
+
+
+REQUIREMENTS
+
+A host with a USB port.  Ideally, either a UHCI (Intel) or OHCI
+(Compaq and others) hardware port should work.  However, I've only
+been able to really use an OHCI controller.  I did have access to a
+system with a UHCI controller but some very limited testing did not
+produce satisfactory results.  Luke Ordelmans
+<postbus@ordelmans.demon.nl> has reported success using the UHCI host
+controller with kernel 2.3.18 and a ChainTech motherboard.  Here
+lately I've been having better success with the ohci-hcd driver.  But
+since Linux USB support is still in a state of constant development
+that may change at a later date.  I am confident that eventually all
+the host contollers will perform without incident.
+
+A Linux kernel with USB support (preferably linux-2.3.18+)
+
+A Linux kernel with USB Scanner support.
+
+
+CONFIGURATION
+
+Using `make menuconfig` or your prefered method for configuring the
+kernel, select 'Support for USB', 'OHCI/OHCI-HCD/UHCI' depending on
+your hardware, 'USB hub support', and 'USB Scanner support'.  Compile
+and install the modules (you may need to execute `depmod -a` to update
+the module dependencies).  Testing was performed only as modules,
+YMMV.
+
+Add a device for the USB scanner:
+  linux-2.3.22 and above: `mknod /dev/usbscanner c 180 48`
+  linux-2.3.21 and below: `mknod /dev/usbscanner c 16 1`
+
+Set appropriate permissions for /dev/usbscanner (don't forget about
+group and world permissions).  Both read and write permissions are
+required for proper operation.
+
+Load the appropriate modules (if compiled as modules):
+
+  OHCI:
+    modprobe usb-ohci
+    modprobe scanner
+
+  OHCI-HCD:
+    modprobe usb-ohci-hcd
+    modprobe hub
+    modprobe scanner
+
+  UHCI:
+    modprobe usb-uhci
+    modprobe hub (don't know if this is required or not)
+    modprobe scanner
+
+That's it.  SANE should now be able to access the device.  
+
+There is a small test program (hp_scan.c -- appended below) that can
+be used to test the scanner device if it's an HP scanner that supports
+SCL.  Its purpose is to test the driver without having to
+retrieve/configure SANE.  Hp_scan.c will scan the entire bed and put
+the output into a file called 'out.dat' in the current directory.  The
+data in the file is raw data so it's not very useful for imaging.
+
+
+MODULE PARAMETERS
+
+If you have a device that wish to experiment with or try using this
+driver with, but the Vendor and Product ID's are not coded in, don't
+despair.  If the driver was compiled as a module, you can pass options
+to the driver.  Simply add 'options scanner vendor=0x####
+product=0x****' to the conf.modules/modules.conf file replacing the
+#'s and the *'s with the correct ID's.  The ID's can be retrieved from
+the messages file or using `cat /proc/bus/usb/devices` if USB /proc
+support was selected during kernel configuration.
+
+
+BUGS
+
+If you encounter any problems feel free to drop me an email.
+
+David /\/elson
+dnelson@jump.net
+http://www.jump.net/~dnelson
+
+--------------- snip -- hp_scan.c -- snip ---------------
+/*
+
+This is a really crude attempt at writing a short test program.  It's
+mostly only to be used to test connectivity with USB HP scanners that
+understand SCL.  Currently, the supported models are 4100C, 5200C,
+6200C, and the 6300C.  Note that the 4200C is *NOT* acceptable.
+
+Copyright (C) David E. Nelson <dnelson@jump.net>, 1999
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <error.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/*
+   Gray Output produces about a 8945400 byte file.
+   Color Output produces a 26836200 byte file. 
+   
+   To compile: gcc -o hp_scan hp_scan.c
+*/
+
+// #define COLOR /* Undef to scan GrayScale */
+
+int send_cmd(int, const char *, int);
+int read_cmd(int, char *, int);
+
+int
+main(void) {
+
+       ssize_t cnt = 0, total_cnt = 0;
+
+       FILE *fpout;
+
+       int fp;
+       int data_size = 32768;
+
+       char *data;
+
+       static char reset_cmd[] = {'\x1b','E'};
+
+#ifdef COLOR
+       static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */
+       static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */
+#else
+       static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */
+       static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */
+#endif
+
+       static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'};
+       static char start_scan_cmd[] = {'\x1b','*','f','0','S'};
+       
+       if(!(data=malloc(data_size))) {
+               perror("malloc failed");
+               exit (1);
+       }
+       
+       if((fp=open("/dev/usbscanner", O_RDWR)) < 0) {
+               perror("Unable to open scanner device");
+               exit (1);
+       }
+
+       if((fpout=fopen("out.dat", "w+")) == NULL) {
+               perror("Unable to open ouput file");
+               exit(1);
+       }
+
+       send_cmd(fp, reset_cmd, sizeof(reset_cmd));
+       send_cmd(fp, data_type_cmd, sizeof(data_type_cmd));
+       send_cmd(fp, data_width_cmd, sizeof(data_width_cmd));
+       send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd));
+
+       while ((cnt = read(fp, data, data_size)) > 0) {
+               printf("Read: %u\n", cnt); 
+               if(fwrite(data, sizeof(char), cnt, fpout) < 0) {
+                       perror("Write to output file failed");
+                       exit (1);
+               }
+               total_cnt += cnt;
+       }
+       if (cnt < 0) {
+               perror("Read from scanner failed");
+               exit (1);
+       }
+
+       printf("\nRead %lu bytes.\n", total_cnt);
+
+       send_cmd(fp, reset_cmd, sizeof(reset_cmd));
+
+       close(fp);
+       fclose(fpout);
+       return (0);
+}
+
+int
+send_cmd(int fp, const char * cmd, int length) {
+
+       int result;
+       int x;
+
+       if((result = write(fp, cmd, length)) != length) {
+               printf ("Write warning: %d bytes requested, %d written\n");
+       } else if (result < 0) {
+               perror ("send_cmd failure");
+               exit (1);
+       }
+       return (result);
+}
+       
+int
+read_cmd(int fp, char * response, int length) {
+
+       return read(fp, response, length);
+
+}
diff --git a/Documentation/usb/uhci.txt b/Documentation/usb/uhci.txt
new file mode 100644 (file)
index 0000000..53aaa11
--- /dev/null
@@ -0,0 +1,165 @@
+Specification and Internals for the New UHCI Driver (Whitepaper...)
+
+       brought to you by
+
+       Georg Acher, acher@in.tum.de (executive slave) (base guitar)
+       Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
+       Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
+       $Id: README.uhci,v 1.1 1999/12/14 14:03:02 fliegl Exp $
+
+This document and the new uhci sources can be found on
+               http://hotswap.in.tum.de/usb
+
+1. General issues
+
+1.1 Why a new UHCI driver, we already have one?!?
+
+Correct, but its internal structure got more and more mixed up by the (still
+ongoing) efforts to get isochronous transfers (ISO) to work.
+Since there is an increasing need for reliable ISO-transfers (especially 
+for USB-audio needed by TS and for a DAB-USB-Receiver build by GA and DF), 
+this state was a bit unsatisfying in our opinion, so we've decided (based
+on knowledge and experiences with the old UHCI driver) to start 
+from scratch with a new approach, much simpler but at the same time more 
+powerful.
+It is inspired by the way Win98/Win2000 handles USB requests via URBs,
+but it's definitely 100% free of MS-code and doesn't crash while 
+unplugging an used ISO-device like Win98 ;-)
+Some code for HW setup and root hub management was taken from the 
+original UHCI driver, but heavily modified to fit into the new code.
+The invention of the basic concept, and major coding were completed in two 
+days (and nights) on the 16th and 17th of October 1999, now known as the
+great USB-October-Revolution started by GA, DF, and TS ;-)
+
+Since the concept is in no way UHCI dependant, we hope that it will also be 
+transfered to the OHCI-driver, so both drivers share a common API.
+
+1.2. Advantages and disadvantages
+
++ All USB transfer types work now!
++ Asynchronous operation
++ Simple, but powerful interface (only two calls for start and cancel)
++ Easy migration to the new API, simplified by a compatibility API
++ Simple usage of ISO transfers
++ Automatic linking of requests
++ ISO transfers allow variable length for each frame and striping
++ No CPU dependent and non-portable atomic memory access, no asm()-inlines
++ Tested on x86 and Alpha
+
+- Rewriting for ISO transfers needed
+
+1.3. Is there some compatibility to the old API?
+
+Yes, but only for control, bulk and interrupt transfers. We've implemented 
+some wrapper calls for these transfer types. The usbcore works fine with 
+these wrappers. For ISO there's no compatibility, because the old ISO-API 
+and its semantics were unnecessary complicated in our opinion.
+
+1.4. What's really working?
+
+As said above, CTRL und BULK already work fine even with the wrappers,
+so legacy code wouldn't notice the change.
+Regarding to Thomas, ISO transfers now run stable with USB audio.
+INT transfers (e.g. mouse driver) work fine, too.
+
+1.5. Are there any bugs?
+
+No ;-)
+Hm...
+Well, of course this implementation needs extensive testing on all available
+hardware, but we believe that any fixes shouldn't harm the overall concept.
+
+1.6. What should be done next?
+
+A large part of the request handling seems to be identical for UHCI and 
+OHCI, so it would be a good idea to extract the common parts and have only 
+the HW specific stuff in uhci.c. Furthermore, all other USB device drivers
+should need URBification, if they use isochronous or interrupt transfers.
+One thing missing in the current implementation (and the old UHCI driver) 
+is fair queueing for BULK transfers. Since this would need (in principle) 
+the alteration of already constructed TD chains (to switch from depth to 
+breadth execution), another way has to be found. Maybe some simple 
+heuristics work with the same effect.
+
+---------------------------------------------------------------------------
+
+2. Internal structure and mechanisms
+
+To get quickly familiar with the internal structures, here's a short
+description how the new UHCI driver works. However, the ultimate source of
+truth is only uhci.c!
+
+2.1. Descriptor structure (QHs and TDs)
+
+During initialization, the following skeleton is allocated in init_skel:
+
+        framespecific           |           common chain     
+
+framelist[]
+[  0 ]-----> TD --> TD -------\
+[  1 ]-----> TD --> TD --------> TD ----> QH -------> QH -------> QH ---> NULL
+  ...        TD --> TD -------/
+[1023]-----> TD --> TD ------/
+            
+            ^^     ^^           ^^       ^^          ^^          ^^
+   1024 TDs for   7 TDs for    1 TD for   Start of    Start of    End Chain
+           ISO  INT (2-128ms) 1ms-INT    CTRL Chain  BULK Chain
+
+For each CTRL or BULK transfer a new QH is allocated and the containing data
+transfers are appended as (vertical) TDs. After building the whole QH with its
+dangling TDs, the QH is inserted before the BULK Chain QH (for CTRL) or
+before the End Chain QH (for BULK). Since only the QH->next pointers are
+affected, no atomic memory operation is required. The three QHs in the
+common chain are never equipped with TDs!
+
+For ISO or INT, the TD for each frame is simply inserted into the apropriate
+ISO/INT-TD-chain for the desired frame. The 7 skeleton INT-TDs are scattered
+among the 1024 frames similar to the old UHCI driver.
+
+For CTRL/BULK/ISO, the last TD in the transfer has the IOC-bit set. For INT,
+every TD (there is only one...) has the IOC-bit set.
+
+Besides the data for the UHCI controller (2 or 4 32bit words), the descriptors
+are double-linked through the .vertical and .horizontal elements in the 
+SW data of the descriptor (using the double-linked list structures and 
+operations), but SW-linking occurs only in closed domains, i.e. for each of
+the 1024 ISO-chains and the 8 INT-chains there is a closed cycle. This 
+simplifies all insertions and unlinking operations and avoids costly 
+bus_to_virt()-calls.
+
+2.2. URB structure and linking to QH/TDs
+
+During assembly of the QH and TDs of the requested action, these descriptors
+are stored in urb->urb_list, so the allocated QH/TD descriptors are bound to
+this URB.
+If the assembly was successful and the descriptors were added to the HW chain,
+the corresponding URB is inserted into a global URB list for this controller.
+This list stores all pending URBs.
+
+2.3. Interrupt processing
+
+Since UHCI provides no means to directly detect completed transactions, the
+following is done in each UHCI interrupt (uhci_interrupt()):
+
+For each URB in the pending queue (process_urb()), the ACTIVE-flag of the 
+associated TDs are processed (depending on the transfer type 
+process_{transfer|interrupt|iso}()). If the TDs are not active anymore, 
+they indicate the completion of the transaction and the status is calculated. 
+Inactive QH/TDs are removed from the HW chain (since the host controller
+already removed the TDs from the QH, no atomic access is needed) and 
+eventually the URB is marked as completed (OK or errors) and removed from the 
+pending queue. Then the next linked URB is submitted. After (or immediately 
+before) that, the completion handler is called.
+
+2.4. Unlinking URBs
+
+First, all QH/TDs stored in the URB are unlinked from the HW chain. 
+To ensure that the host controller really left a vertical TD chain, we 
+wait for one frame. After that, the TDs are physically destroyed.
+
+2.5. URB linking and the consequences
+
+Since URBs can be linked and the corresponding submit_urb is called in
+the UHCI-interrupt, all work associated with URB/QH/TD assembly has to be
+interrupt save. This forces kmalloc to use GFP_ATOMIC in the interrupt.
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
new file mode 100644 (file)
index 0000000..053f18d
--- /dev/null
@@ -0,0 +1,42 @@
+This serial driver currently only works with the Belkin and Peracom USB 
+Serial devices. It should also work for the Etek converter, but I do 
+not know the vendor id and device id of that device (if anyone does, 
+please let me know.)
+
+If your device is not compatible with the above models, you can try
+out the "generic" interface. This interface does not provide any type
+of control messages sent to the device, and does not support any kind
+of device flow control. All that is required of your device is that
+it has at least one bulk in endpoint, or one bulk out endpoint.
+To enable the driver to recognize your device, build the driver as
+a module and load it by the following invocation:
+       insmod usb-serial.o vendor=0x#### product=0x####
+where the #### is replaced with the hex representation of your device's
+vendor id and product id.
+
+The driver can handle enumerating the device, and sending and receiving
+data from the converter. However, since I do not have a spec for the Belkin,
+Peracom, and eTek devices, and the raw dumps from the Win98 driver are 
+confusing, and eTek keeps giving me the run around, no control signals are 
+currently handled, and the data will most likely come through on a baud
+rate that you are not expecting. So if you have these devices, do not 
+expect the correct data to show up at either end. 
+
+The major number that the driver uses is 188 so to use the driver, create
+the following nodes:
+mknod /dev/ttyUSB0 c 188 0
+mknod /dev/ttyUSB1 c 188 1
+mknod /dev/ttyUSB2 c 188 2
+mknod /dev/ttyUSB3 c 188 3
+
+then plug in a device and use your friendly terminal program to see what
+happens.
+
+If anyone has any problems getting the device to enumerate, or data to 
+flow through it, please contact me.
+
+
+
+greg k-h
+greg@kroah.com
+
index 373ad16eead5c1e4398dc1cc087742c35016689e..a56a30e690155a3f7c90898166b4b3af35c7a6ef 100644 (file)
@@ -192,7 +192,7 @@ S:  Maintained
 
 CIRRUS LOGIC GENERIC FBDEV DRIVER
 P:     Jeff Garzik
-M:     jgarzik@pobox.com
+M:     jgarzik@mandrakesoft.com
 L:     linux-fbdev@vuser.vu.union.edu
 S:     Maintained
 
@@ -996,7 +996,7 @@ S:  Maintained
 
 VIA 82Cxxx AUDIO DRIVER
 P:     Jeff Garzik
-M:     jgarzik@pobox.com
+M:     jgarzik@mandrakesoft.com
 S:     Maintained
 
 VIDEO FOR LINUX
index f27323a39edf680efdd73f5009a77d942105ef32..e8afdf387a479106ef069a911788659d9a6b7d21 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 36
+SUBLEVEL = 37
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -343,6 +343,18 @@ init/main.o: init/main.c include/config/MARKER
 fs lib mm ipc kernel drivers net: dummy
        $(MAKE) $(subst $@, _dir_$@, $@)
 
+TAGS: dummy
+       etags `find include/asm-$(ARCH) -name '*.h'`
+       find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
+       find $(SUBDIRS) init -name '*.c' | xargs etags -a
+
+# Exuberant ctags works better with -I 
+tags: dummy
+       CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__initlocaldata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
+       ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \
+       find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs ctags $$CTAGSF -a && \
+       find $(SUBDIRS) init -name '*.c' | xargs ctags $$CTAGSF -a
+
 MODFLAGS = -DMODULE
 ifdef CONFIG_MODULES
 ifdef CONFIG_MODVERSIONS
@@ -446,7 +458,7 @@ mrproper: clean archmrproper
 distclean: mrproper
        rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
                -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-               -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
+               -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS tags
 
 backup: mrproper
        cd .. && tar cf - linux/ | gzip -9 > backup.gz
index 7c0624c000ddf9f1063e7ac021ee16ddbcee1b3c..aa0c450b41983f34064435b02399a0f83411f24b 100644 (file)
 #include <asm/hwrpb.h>
 #include <asm/processor.h>
 
-extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
+extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *);
 extern int do_pipe(int *);
 
-extern struct file_operations *get_blkfops(unsigned int);
-extern struct file_operations *get_chrfops(unsigned int);
-
-extern kdev_t get_unnamed_dev(void);
-extern void put_unnamed_dev(kdev_t);
-
 extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
 extern asmlinkage unsigned long sys_brk(unsigned long);
 
@@ -400,18 +394,16 @@ struct procfs_args {
        uid_t exroot;
 };
 
-static int getdev(const char *name, int rdonly, struct dentry **dp)
+static struct dentry *getdev(const char *name, int rdonly)
 {
-       kdev_t dev;
        struct dentry *dentry;
        struct inode *inode;
-       struct file_operations *fops;
        int retval;
 
        dentry = namei(name);
        retval = PTR_ERR(dentry);
        if (IS_ERR(dentry))
-               return retval;
+               return dentry;
 
        retval = -ENOTBLK;
        inode = dentry->d_inode;
@@ -421,48 +413,20 @@ static int getdev(const char *name, int rdonly, struct dentry **dp)
        retval = -EACCES;
        if (IS_NODEV(inode))
                goto out_dput;
-
-       retval = -ENXIO;
-       dev = inode->i_rdev;
-       if (MAJOR(dev) >= MAX_BLKDEV)
-               goto out_dput;
-
-       retval = -ENODEV;
-       fops = get_blkfops(MAJOR(dev));
-       if (!fops)
-               goto out_dput;
-       if (fops->open) {
-               struct file dummy;
-               memset(&dummy, 0, sizeof(dummy));
-               dummy.f_dentry = dentry;
-               dummy.f_mode = rdonly ? 1 : 3;
-               retval = fops->open(inode, &dummy);
-               if (retval)
-                       goto out_dput;
-       }
-       *dp = dentry;
-       retval = 0;
-out:
-       return retval;
+       return dentry;
 
 out_dput:
        dput(dentry);
-       goto out;
-}
-
-static void putdev(struct dentry *dentry)
-{
-       struct file_operations *fops;
-
-       fops = get_blkfops(MAJOR(dentry->d_inode->i_rdev));
-       if (fops->release)
-               fops->release(dentry->d_inode, NULL);
+       return ERR_PTR(retval);
 }
 
 /*
  * We can't actually handle ufs yet, so we translate UFS mounts to
  * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS
  * layout is so braindead it's a major headache doing it.
+ *
+ * Just how long ago was it written? OTOH our UFS driver may be still
+ * unhappy with OSF UFS. [CHECKME]
  */
 static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
 {
@@ -474,13 +438,12 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
        if (copy_from_user(&tmp, args, sizeof(tmp)))
                goto out;
 
-       retval = getdev(tmp.devname, 0, &dentry);
-       if (retval)
+       dentry = getdev(tmp.devname, 0);
+       retval = PTR_ERR(dentry);
+       if (IS_ERR(dentry)
                goto out;
-       retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname, 
+       retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, 
                                "ext2", flags, NULL);
-       if (retval)
-               putdev(dentry);
        dput(dentry);
 out:
        return retval;
@@ -496,13 +459,12 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
        if (copy_from_user(&tmp, args, sizeof(tmp)))
                goto out;
 
-       retval = getdev(tmp.devname, 1, &dentry);
-       if (retval)
+       dentry = getdev(tmp.devname, 1);
+       retval = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
                goto out;
-       retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname, 
+       retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, 
                                "iso9660", flags, NULL);
-       if (retval)
-               putdev(dentry);
        dput(dentry);
 out:
        return retval;
@@ -510,19 +472,12 @@ out:
 
 static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
 {
-       kdev_t dev;
        int retval;
        struct procfs_args tmp;
 
        if (copy_from_user(&tmp, args, sizeof(tmp)))
                return -EFAULT;
-       dev = get_unnamed_dev();
-       if (!dev)
-               return -ENODEV;
-       retval = do_mount(dev, "", dirname, "proc", flags, NULL);
-       if (retval)
-               put_unnamed_dev(dev);
-       return retval;
+       return do_mount(NULL, "", dirname, "proc", flags, NULL);
 }
 
 asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data)
index f26991f55813fadba636cd75ab81f65afd243416..78025bec9eed99410508ce3b67669755397a1a5e 100644 (file)
@@ -141,7 +141,7 @@ sio_collect_irq_levels(void)
        struct pci_dev *dev;
 
        /* Iterate through the devices, collecting IRQ levels.  */
-       for (dev = pci_devices; dev; dev = dev->next) {
+       pci_for_each_dev(dev) {
                if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
                    (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
                        continue;
index 041d4f4ed0eb316eb7fa43b966a66fd2c184a232..b9b7d57b4078da5cd7c9bbd6cc85fa37eb3bf3d7 100644 (file)
@@ -24,7 +24,7 @@ void pcibios_report_device_errors(void)
 {
        struct pci_dev *dev;
 
-       for (dev = pci_devices; dev; dev = dev->next) {
+       pci_for_each_dev(dev) {
                u16 status;
 
                pci_read_config_word(dev, PCI_STATUS, &status);
@@ -121,11 +121,12 @@ static void __init pcibios_claim_resources(void)
        struct pci_dev *dev;
        int idx;
 
-       for (dev = pci_devices; dev; dev = dev->next)
+       pci_for_each_dev(dev) {
                for (idx = 0; idx < PCI_NUM_RESOURCES; idx++)
                        if (dev->resource[idx].flags &&
                            dev->resource[idx].start)
                                pci_claim_resource(dev, idx);
+       }
 }
 
 void __init
index cbfa7b3e8ab809291af6ff25adfb064c9a1633ba..1a08bc3abd06a67bdd6b5920095b61cc915fa369 100644 (file)
@@ -202,9 +202,9 @@ bad_sig:
        xorb    %bh, %bh
        movb    (497), %bl                      # get setup sect from bootsect
        subw    $4, %bx                         # LILO loads 4 sectors of setup
-       shlw    $7, %bx                         # convert to dwords (1sect=2^7 dwords)
+       shlw    $8, %bx                         # convert to words (1sect=2^8 words)
        movw    %bx, %cx
-       shrw    $2, %bx                         # convert to segment
+       shrw    $3, %bx                         # convert to segment
        addw    $SYSSEG, %bx
        movw    %bx, %cs:start_sys_seg
 # Move rest of setup code/data to here
index 4ba8ee9b96f7960c9ffa13e0728de865ccc2057b..1db3bec2e9347f42db57d8e69b2909cf8146c825 100644 (file)
@@ -120,6 +120,12 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 source drivers/parport/Config.in
 
 bool 'ACPI support' CONFIG_ACPI
+if [ "$CONFIG_ACPI" != "n" ]; then
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+     bool '  Enter S1 for sleep' CONFIG_ACPI_S1_SLEEP
+   fi
+fi
+
 bool 'Advanced Power Management BIOS support' CONFIG_APM
 if [ "$CONFIG_APM" != "n" ]; then
    bool '  Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
index e3572f20cc1462250d2a1fa60d1de60478cf9244..c52bef6432d88fc15e0cdb94f5377d8c698113aa 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/string.h>
 #include <linux/miscdevice.h>
 #include <linux/sched.h>
 #include <linux/time.h>
@@ -120,6 +121,9 @@ static unsigned long acpi_p_blk = 0;
 static int acpi_p_lvl2_tested = 0;
 static int acpi_p_lvl3_tested = 0;
 
+static int acpi_disabled = 0;
+int acpi_active = 0;
+
 // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
 static unsigned long acpi_slp_typ[] = 
 {
@@ -1146,8 +1150,10 @@ static int acpi_do_sleep(ctl_table *ctl,
        }
        else
        {
+#ifdef CONFIG_ACPI_S1_SLEEP
                acpi_enter_sx(ACPI_S1);
                acpi_enter_sx(ACPI_S0);
+#endif
        }
        file->f_pos += *len;
        return 0;
@@ -1160,29 +1166,30 @@ static int __init acpi_init(void)
 {
        int pid;
 
+       if (acpi_disabled)
+               return -ENODEV;
+
        if (acpi_find_tables() && acpi_find_piix4()) {
                // no ACPI tables and not PIIX4
                return -ENODEV;
        }
 
        /*
-        * Are the latencies in uS or in ticks in the tables? 
-        * Maybe this should do ACPI_uS_TO_TMR_TICKS?
-        *
-        * Whatever. Internally we always keep them in timer
+        * Internally we always keep latencies in timer
         * ticks, which is simpler and more consistent (what is
         * an uS to us?). Besides, that gives people more
         * control in the /proc interfaces.
         */
        if (acpi_facp->p_lvl2_lat
            && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
-               acpi_p_lvl2_lat = acpi_facp->p_lvl2_lat;
-               acpi_enter_lvl2_lat = ACPI_TMR_HZ / 1000;
+               acpi_p_lvl2_lat = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl2_lat);
+               acpi_enter_lvl2_lat = ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
        }
        if (acpi_facp->p_lvl3_lat
            && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
-               acpi_p_lvl3_lat = acpi_facp->p_lvl3_lat;
-               acpi_enter_lvl3_lat = acpi_facp->p_lvl3_lat * 5;
+               acpi_p_lvl3_lat = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat);
+               acpi_enter_lvl3_lat
+                       = ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat * 5);
        }
 
        if (acpi_facp->sci_int
@@ -1206,6 +1213,8 @@ static int __init acpi_init(void)
 
        acpi_power_off = acpi_power_off_handler;
 
+       acpi_active = 1;
+
        /*
         * Set up the ACPI idle function. Note that we can't really
         * do this with multiple CPU's, we'd need a per-CPU ACPI
@@ -1240,6 +1249,22 @@ static void __exit acpi_exit(void)
        acpi_destroy_tables();
 }
 
+static int __init acpi_setup(char *str)
+{
+       while (str && *str) {
+               if (strncmp(str, "off", 3) == 0)
+                       acpi_disabled = 1;
+               else if (strncmp(str, "on", 2) == 0)
+                       acpi_disabled = 0;
+               str = strpbrk(str, ",");
+               if (str)
+                       str += strspn(str, ",");
+       }
+       return 1;
+}
+
+__setup("acpi=", acpi_setup);
+
 /*
  * Register a device with the ACPI subsystem
  */
index c6c51ccffa046fb62f61b261ace069fb7a4b4abc..8f3d24645f85b16b23cbe6954802ec74b37d6437 100644 (file)
@@ -1491,6 +1491,13 @@ static int __init apm_init(void)
                APM_INIT_ERROR_RETURN;
        }
 
+#ifdef CONFIG_ACPI
+       if (acpi_active) {
+               printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+               APM_INIT_ERROR_RETURN;
+       }
+#endif
+
        /*
         * Set up a segment that references the real mode segment 0x40
         * that extends up to the end of page zero (that we have reserved).
index 3c72c9cb53bb629dbf9772f990f99baf42ee9e54..9f75d94bf002c941b8e32cf9f3a50b9635ab7449 100644 (file)
@@ -56,6 +56,9 @@ EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 EXPORT_SYMBOL(csum_partial_copy_generic);
index 48fc3519ab871cc4301817a259d30c720c31a0fa..a111eb516f1272dcfa7b9723fd57b6b0f3596857 100644 (file)
@@ -707,9 +707,11 @@ void free_irq(unsigned int irq, void *dev_id)
                        }
                        spin_unlock_irqrestore(&irq_controller_lock,flags);
 
+#ifdef __SMP__
                        /* Wait to make sure it's not being used on another CPU */
                        while (irq_desc[irq].status & IRQ_INPROGRESS)
                                barrier();
+#endif
                        kfree(action);
                        return;
                }
index 2197597c880cf578a0717e26cae749c9210e7ed9..e94868cd979b542f72b7893671fbf50bbe6681cd 100644 (file)
@@ -12,7 +12,7 @@
  *     Hannover, Germany
  *     hm@ix.de
  *
- * Copyright 1997--1999 Martin Mares <mj@suse.cz>
+ * Copyright 1997--2000 Martin Mares <mj@suse.cz>
  *
  * For more information, please consult the following manuals (look at
  * http://www.pcisig.com/ for how to get them):
@@ -180,14 +180,17 @@ int pci_assign_resource(struct pci_dev *dev, int i)
  *         as well.
  */
 
-static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
 {
+       struct list_head *ln;
+       struct pci_bus *bus;
        struct pci_dev *dev;
        int idx;
        struct resource *r, *pr;
 
        /* Depth-First Search on bus tree */
-       while (bus) {
+       for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+               bus = pci_bus_b(ln);
                if ((dev = bus->self)) {
                        for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
                                r = &dev->resource[idx];
@@ -198,9 +201,7 @@ static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
                                        printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
                        }
                }
-               if (bus->children)
-                       pcibios_allocate_bus_resources(bus->children);
-               bus = bus->next;
+               pcibios_allocate_bus_resources(&bus->children);
        }
 }
 
@@ -211,7 +212,7 @@ static void __init pcibios_allocate_resources(int pass)
        u16 command;
        struct resource *r, *pr;
 
-       for(dev=pci_devices; dev; dev=dev->next) {
+       pci_for_each_dev(dev) {
                pci_read_config_word(dev, PCI_COMMAND, &command);
                for(idx = 0; idx < 6; idx++) {
                        r = &dev->resource[idx];
@@ -255,7 +256,7 @@ static void __init pcibios_assign_resources(void)
        int idx;
        struct resource *r;
 
-       for(dev=pci_devices; dev; dev=dev->next) {
+       pci_for_each_dev(dev) {
                int class = dev->class >> 8;
 
                /* Don't touch classless devices and host bridges */
@@ -293,7 +294,8 @@ static void __init pcibios_assign_resources(void)
 
 void __init pcibios_resource_survey(void)
 {
-       pcibios_allocate_bus_resources(pci_root);
+       DBG("PCI: Allocating resources\n");
+       pcibios_allocate_bus_resources(&pci_root_buses);
        pcibios_allocate_resources(0);
        pcibios_allocate_resources(1);
        pcibios_assign_resources();
index d0ff0b6c3d19c7395d9cb102153d3979e6c76b41..ef1cc651afe16dabd4c55285b8dbd2beac7ea7db 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Low-Level PCI Support for PC
  *
- *     (c) 1999 Martin Mares <mj@suse.cz>
+ *     (c) 1999--2000 Martin Mares <mj@suse.cz>
  */
 
 #include <linux/config.h>
@@ -22,6 +22,8 @@
 
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
+static struct pci_bus *pci_root_bus;
+
 /*
  * IRQ routing table provided by the BIOS
  */
@@ -624,26 +626,31 @@ static struct pci_ops * __init pci_find_bios(void)
 
 static void __init pcibios_sort(void)
 {
-       struct pci_dev *dev = pci_devices;
-       struct pci_dev **last = &pci_devices;
-       struct pci_dev *d, **dd, *e;
-       int idx;
+       LIST_HEAD(sorted_devices);
+       struct list_head *ln;
+       struct pci_dev *dev, *d;
+       int idx, found;
        unsigned char bus, devfn;
 
        DBG("PCI: Sorting device list...\n");
-       while ((e = dev)) {
-               idx = 0;
-               while (pci_bios_find_device(e->vendor, e->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
+       while (pci_devices.next != &pci_devices) {
+               ln = pci_devices.next;
+               list_del(ln);
+               dev = pci_dev_g(ln);
+               idx = found = 0;
+               while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
                        idx++;
-                       for(dd=&dev; (d = *dd); dd = &d->next) {
+                       for (ln=pci_devices.next; ln != &pci_devices; ln=ln->next) {
+                               d = pci_dev_g(ln);
                                if (d->bus->number == bus && d->devfn == devfn) {
-                                       *dd = d->next;
-                                       *last = d;
-                                       last = &d->next;
+                                       list_del(&d->global_list);
+                                       list_add_tail(&d->global_list, &sorted_devices);
+                                       if (d == dev)
+                                               found = 1;
                                        break;
                                }
                        }
-                       if (!d) {
+                       if (ln == &pci_devices) {
                                printk("PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn);
                                /*
                                 * We must not continue scanning as several buggy BIOSes
@@ -652,16 +659,14 @@ static void __init pcibios_sort(void)
                                break;
                        }
                }
-               if (e == dev) {
+               if (!found) {
                        printk("PCI: Device %02x:%02x not found by BIOS\n",
                                dev->bus->number, dev->devfn);
-                       d = dev;
-                       dev = dev->next;
-                       *last = d;
-                       last = &d->next;
+                       list_del(&dev->global_list);
+                       list_add_tail(&dev->global_list, &sorted_devices);
                }
        }
-       *last = NULL;
+       list_splice(&sorted_devices, &pci_devices);
 }
 
 /*
@@ -736,16 +741,19 @@ static struct irq_routing_table * __init pcibios_get_irq_routing_table(void)
 
 static void __init pcibios_fixup_ghosts(struct pci_bus *b)
 {
-       struct pci_dev *d, *e, **z;
+       struct list_head *ln, *mn;
+       struct pci_dev *d, *e;
        int mirror = PCI_DEVFN(16,0);
        int seen_host_bridge = 0;
        int i;
 
        DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
-       for(d=b->devices; d && d->devfn < mirror; d=d->sibling) {
+       for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+               d = pci_dev_b(ln);
                if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
                        seen_host_bridge++;
-               for(e=d->next; e; e=e->sibling) {
+               for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+                       e = pci_dev_b(mn);
                        if (e->devfn != d->devfn + mirror ||
                            e->vendor != d->vendor ||
                            e->device != d->device ||
@@ -758,20 +766,23 @@ static void __init pcibios_fixup_ghosts(struct pci_bus *b)
                                        continue;
                        break;
                }
-               if (!e)
+               if (mn == &b->devices)
                        return;
        }
        if (!seen_host_bridge)
                return;
        printk("PCI: Ignoring ghost devices on bus %02x\n", b->number);
-       for(e=b->devices; e->sibling != d; e=e->sibling);
-       e->sibling = NULL;
-       for(z=&pci_devices; (d=*z);)
-               if (d->bus == b && d->devfn >= mirror) {
-                       *z = d->next;
-                       kfree_s(d, sizeof(*d));
+
+       ln = &b->devices;
+       while (ln->next != &b->devices) {
+               d = pci_dev_b(ln->next);
+               if (d->devfn >= mirror) {
+                       list_del(&d->global_list);
+                       list_del(&d->bus_list);
+                       kfree(d);
                } else
-                       z = &d->next;
+                       ln = ln->next;
+       }
 }
 
 /*
@@ -783,10 +794,10 @@ static void __init pcibios_fixup_ghosts(struct pci_bus *b)
  */
 static void __init pcibios_fixup_peer_bridges(void)
 {
-       struct pci_bus *b = pci_root;
+       struct list_head *ln;
+       struct pci_bus *b = pci_root_bus;
        int n, cnt=-1;
-       struct pci_dev *d;
-       struct pci_ops *ops = pci_root->ops;
+       struct pci_ops *ops = pci_root_bus->ops;
 
 #ifdef CONFIG_PCI_DIRECT
        /*
@@ -798,8 +809,10 @@ static void __init pcibios_fixup_peer_bridges(void)
                return;
 #endif
 
-       for(d=b->devices; d; d=d->sibling)
-               if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+       DBG("PCI: Peer bridge fixup\n");
+
+       for(ln=b->devices.next; ln != &b->devices; ln=ln->next)
+               if ((pci_dev_b(ln)->class >> 8) == PCI_CLASS_BRIDGE_HOST)
                        cnt++;
        n = b->subordinate + 1;
        while (n <= 0xff) {
@@ -864,9 +877,9 @@ static void __init pci_fixup_i450nx(struct pci_dev *d)
                pci_read_config_byte(d, reg++, &subb);
                DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
                if (busno)
-                       pci_scan_bus(busno, pci_root->ops, NULL);       /* Bus A */
+                       pci_scan_bus(busno, pci_root_bus->ops, NULL);   /* Bus A */
                if (suba < subb)
-                       pci_scan_bus(suba+1, pci_root->ops, NULL);      /* Bus B */
+                       pci_scan_bus(suba+1, pci_root_bus->ops, NULL);  /* Bus B */
        }
 }
 
@@ -879,7 +892,7 @@ static void __init pci_fixup_rcc(struct pci_dev *d)
        u8 busno;
        pci_read_config_byte(d, 0x44, &busno);
        printk("PCI: RCC host bridge: secondary bus %02x\n", busno);
-       pci_scan_bus(busno, pci_root->ops, NULL);
+       pci_scan_bus(busno, pci_root_bus->ops, NULL);
 }
 
 static void __init pci_fixup_compaq(struct pci_dev *d)
@@ -891,7 +904,7 @@ static void __init pci_fixup_compaq(struct pci_dev *d)
        u8 busno;
        pci_read_config_byte(d, 0xc8, &busno);
        printk("PCI: Compaq host bridge: secondary bus %02x\n", busno);
-       pci_scan_bus(busno, pci_root->ops, NULL);
+       pci_scan_bus(busno, pci_root_bus->ops, NULL);
 }
 
 static void __init pci_fixup_umc_ide(struct pci_dev *d)
@@ -1000,7 +1013,7 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
                 *  It might be a secondary bus, but in this case its parent is already
                 *  known (ascending bus order) and therefore pci_scan_bus returns immediately.
                 */
-               if (busmap[i] && pci_scan_bus(i, pci_root->ops, NULL))
+               if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
                        printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
 }
 
@@ -1063,7 +1076,6 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
        case ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0):
        case ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0):
        case ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0):
-       case ID(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533):
                /* Intel PIIX: PIRQ holds configuration register address */
                pci_read_config_byte(router, pirq, &x);
                if (x < 16) {
@@ -1078,6 +1090,7 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
                }
                DBG(" -> [PIIX] sink\n");
                return NULL;
+       case ID(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533):
        default:
                DBG(" -> unknown router %04x/%04x\n", rt->rtr_vendor, rt->rtr_device);
                if (newirq && mask == (1 << newirq)) {
@@ -1096,6 +1109,7 @@ static void __init pcibios_fixup_irqs(void)
        struct pci_dev *dev;
        u8 pin;
 
+       DBG("PCI: IRQ fixup\n");
        rtable = pirq_table = pcibios_find_irq_routing_table();
 #ifdef CONFIG_PCI_BIOS
        if (!rtable && pci_bios_present)
@@ -1105,7 +1119,7 @@ static void __init pcibios_fixup_irqs(void)
        if (rtable)
                pcibios_irq_peer_trick(rtable);
 
-       for(dev=pci_devices; dev; dev=dev->next) {
+       pci_for_each_dev(dev) {
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 #if defined(CONFIG_X86_IO_APIC)
                /*
@@ -1198,7 +1212,7 @@ void __init pcibios_init(void)
        }
 
        printk("PCI: Probing PCI hardware\n");
-       pci_scan_bus(0, ops, NULL);
+       pci_root_bus = pci_scan_bus(0, ops, NULL);
 
        pcibios_fixup_irqs();
        if (pci_probe & PCI_PEER_FIXUP)
index 2ba24c8b383ec6515d611e1ceefdcfbe1cc08d83..401a4ee13672816be1c97767f8f78ecd94ab665e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Low-Level PCI Support for SGI Visual Workstation
  *
- *     (c) 1999 Martin Mares <mj@suse.cz>
+ *     (c) 1999--2000 Martin Mares <mj@suse.cz>
  */
 
 #include <linux/config.h>
@@ -85,7 +85,7 @@ static void __init pcibios_fixup_irqs(void)
        u8 pin;
        int irq;
 
-       for(dev=pci_devices; dev; dev=dev->next) {
+       pci_for_each_dev(dev) {
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
                dev->irq = 0;
                if (!pin)
index 55b762bbdd9c5b17adbfd6ddee07fef50bb445f2..082fda543516476ef495f29f12e03fa9a888c8d2 100644 (file)
@@ -449,69 +449,6 @@ static void __init layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
 
 #endif /* !PCI_MODIFY */
 
-/*
- * Given the vendor and device ids, find the n'th instance of that device
- * in the system.
- */
-
-int pcibios_find_device(unsigned short vendor, unsigned short device_id,
-                       unsigned short index, unsigned char *bus,
-                       unsigned char *devfn)
-{
-       unsigned int curr = 0;
-       struct pci_dev *dev;
-
-       for (dev = pci_devices; dev; dev = dev->next)
-       {
-               if (dev->vendor == vendor && dev->device == device_id)
-               {
-                       if (curr == index)
-                       {
-                               *devfn = dev->devfn;
-                               *bus = dev->bus->number;
-                               return PCIBIOS_SUCCESSFUL;
-                       }
-                       ++curr;
-               }
-       }
-       return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-/*
- * Given the class, find the n'th instance of that device
- * in the system.
- */
-
-int pcibios_find_class(unsigned int class_code, unsigned short index,
-                      unsigned char *bus, unsigned char *devfn)
-{
-       unsigned int curr = 0;
-       struct pci_dev *dev;
-
-       for (dev = pci_devices; dev; dev = dev->next)
-       {
-               if (dev->class == class_code)
-               {
-                       if (curr == index)
-                       {
-                               *devfn = dev->devfn;
-                               *bus = dev->bus->number;
-                               return PCIBIOS_SUCCESSFUL;
-                       }
-                       ++curr;
-               }
-       }
-       return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-int pcibios_present(void)
-{
-       if (MACH_IS_HADES)
-               return 1;
-       else
-               return 0;
-}
-
 void __init pcibios_init(void)
 {
        printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
@@ -574,7 +511,7 @@ void __init pcibios_fixup(void)
         * Scan the tree, allocating PCI memory and I/O space.
         */
 
-       layout_bus(&pci_root, orig_mem_base, orig_io_base);
+       layout_bus(pci_bus_b(pci_root.next), orig_mem_base, orig_io_base);
 
        pci_mem_base = orig_mem_base;
        pci_io_base = orig_io_base;
index b1d7f49dcda1f05bbf36ba4a0ae6376ce9ed30fa..3634e876ced0462d8a727fbdafeaca695c074c62 100644 (file)
@@ -30,7 +30,7 @@ static void sni_rm200_pcibios_fixup (void)
 {
        struct pci_dev *dev;
 
-       for (dev=pci_devices; dev; dev=dev->next) {
+       pci_for_each_dev(dev) {
                /*
                 * TODO: Take care of RM300 revision D boards for where the
                 * network slot became an ordinary PCI slot.
index 88686acc41704b11226c389f0ef070654b771f2a..b93bc45f79506ca00e48816a413ce8a9dc63e0b2 100644 (file)
@@ -282,8 +282,7 @@ chrp_pcibios_fixup(void)
        }
        
        /* PCI interrupts are controlled by the OpenPIC */
-       for( dev=pci_devices ; dev; dev=dev->next )
-       {
+       pci_for_each_dev(dev) {
                if ( dev->irq )
                        dev->irq = openpic_to_irq( dev->irq );
                /* these need to be absolute addrs for OF and Matrox FB -- Cort */
index 054eee9189c8bb8888cadfa9b08e046a77fc82eb..ec1ff356538c79a2f3110a746f768b9da4d497a9 100644 (file)
@@ -91,15 +91,17 @@ unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
        return start;
 }
 
-static void __init pcibios_claim_resources(struct pci_bus *bus)
+static void __init pcibios_claim_resources(struct list_head *bus_list)
 {
+       struct list_head *ln, *dn;
+       struct pci_bus *bus;
        struct pci_dev *dev;
        int idx;
 
-       while (bus)
-       {
-               for (dev=bus->devices; dev; dev=dev->sibling)
-               {
+       for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+               bus = pci_bus_b(ln);
+               for (dn=bus->devices.next; dn != &bus->devices; dn=dn->next) {
+                       dev = pci_dev_b(dn);
                        for (idx = 0; idx < PCI_NUM_RESOURCES; idx++)
                        {
                                struct resource *r = &dev->resource[idx];
@@ -114,9 +116,7 @@ static void __init pcibios_claim_resources(struct pci_bus *bus)
                                }
                        }
                }
-               if (bus->children)
-                       pcibios_claim_resources(bus->children);
-               bus = bus->next;
+               pcibios_claim_resources(&bus->children);
        }
 }
 
index a9166da348baf66ac15b146e03751b32de388fda..75f8097fd7ab899a29f7b3854e6d42d21d7943ba 100644 (file)
@@ -476,7 +476,7 @@ pmac_pcibios_fixup(void)
         *        honor the existence of multi-function devices where
         *        different functions have different interrupt pins. [mj]
         */
-       for(dev=pci_devices; dev; dev=dev->next)
+       pci_for_each_dev(dev)
        {
                /*
                 * Open Firmware often doesn't initialize the,
index a01962b121c09672f7302cfdce04d613fea35ea9..63375787599e5b5a583051b108454efdc0edc16c 100644 (file)
@@ -998,7 +998,7 @@ prep_pcibios_fixup(void)
        printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
        if (OpenPIC) {
                /* PCI interrupts are controlled by the OpenPIC */
-               for(dev=pci_devices; dev; dev=dev->next) {
+               pci_for_each_dev(dev) {
                        if (dev->bus->number == 0) {
                                        dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
                                pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_PIN, dev->irq);
@@ -1007,8 +1007,7 @@ prep_pcibios_fixup(void)
                return;
        }
 
-       for(dev=pci_devices; dev; dev=dev->next)
-       {
+       pci_for_each_dev(dev) {
                /*
                 * Use our old hard-coded kludge to figure out what
                 * irq this device uses.  This is necessary on things
index 247c673dff3c20df139dff98038efab576d90621..9dcde0a971519a16662bf1fa7500f570ea1ab927 100644 (file)
@@ -721,7 +721,7 @@ struct sunos_nfs_mount_args {
 };
 
 
-extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
+extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *);
 extern dev_t get_unnamed_dev(void);
 extern void put_unnamed_dev(dev_t);
 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
@@ -797,7 +797,6 @@ asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
        char *the_name;
        struct nfs_mount_data linux_nfs_mount;
        struct sunos_nfs_mount_args *sunos_mount = data;
-       dev_t dev;
 
        /* Ok, here comes the fun part: Linux's nfs mount needs a
         * socket connection to the server, but SunOS mount does not
@@ -839,13 +838,7 @@ asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
        linux_nfs_mount.hostname [255] = 0;
        putname (the_name);
        
-       dev = get_unnamed_dev ();
-       
-       ret = do_mount (dev, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
-       if (ret)
-           put_unnamed_dev(dev);
-
-       return ret;
+       return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
 }
 
 asmlinkage int
index 537a79473f04d376c1c6285ff4bac2994a75942a..5ce1cfb93db153246abb7479d4a8443db0934526 100644 (file)
@@ -685,7 +685,7 @@ struct sunos_nfs_mount_args {
        char       *netname;   /* server's netname */
 };
 
-extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
+extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *);
 extern dev_t get_unnamed_dev(void);
 extern void put_unnamed_dev(dev_t);
 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
@@ -767,7 +767,6 @@ asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
        char *the_name;
        struct nfs_mount_data linux_nfs_mount;
        struct sunos_nfs_mount_args *sunos_mount = data;
-       dev_t dev;
 
        /* Ok, here comes the fun part: Linux's nfs mount needs a
         * socket connection to the server, but SunOS mount does not
@@ -809,13 +808,7 @@ asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
        linux_nfs_mount.hostname [255] = 0;
        putname (the_name);
 
-       dev = get_unnamed_dev ();
-       
-       ret = do_mount (dev, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
-       if (ret)
-           put_unnamed_dev(dev);
-
-       return ret;
+       return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
 }
 
 /* XXXXXXXXXXXXXXXXXXXX */
index 59030ebd58dac95589a87239677ad0eaa54c8554..71355d78822c5644ceb05a3b5ff0d718a6293a35 100644 (file)
@@ -1350,10 +1350,6 @@ static int invalidate_drive(int rdev)
 static int fd_ioctl(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long param)
 {
-#define IOCTL_MODE_BIT 8
-#define OPEN_WRITE_BIT 16
-#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
-
        int drive, device;
 
        device = inode->i_rdev;
@@ -1361,8 +1357,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
                RO_IOCTLS(inode->i_rdev, param);
        }
        drive = MINOR(device);
-       if (!IOCTL_ALLOWED)
-               return -EPERM;
        switch (cmd) {
        case FDFMTBEG:
                return 0;
@@ -1544,12 +1538,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
        if (old_dev && old_dev != inode->i_rdev)
                invalidate_buffers(old_dev);
 
-       /* Allow ioctls if we have write-permissions even if read-only open */
-       if (filp->f_mode & 2 || permission(inode, 2) == 0)
-               filp->f_mode |= IOCTL_MODE_BIT;
-       if (filp->f_mode & 2)
-               filp->f_mode |= OPEN_WRITE_BIT;
-
        if (filp->f_flags & O_NDELAY)
                return 0;
 
@@ -1570,12 +1558,9 @@ static void floppy_release(struct inode *inode, struct file *filp)
 {
        int drive;
 
-       drive = inode->i_rdev & 3;
+       drive = MINOR(inode->i_rdev) & 3;
 
-       if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
-               /* if the file is mounted OR (writable now AND writable at open
-                  time) Linus: Does this cover all cases? */
-               block_fsync(inode, filp);
+       block_fsync(inode, filp);
 
        if (fd_ref[drive] < 0)
                fd_ref[drive] = 0;
index 28b56e9e43526e219218257091b01d56e05920a9..5c06b91a4e8bddea951cbc676f8bd25062a1aeff 100644 (file)
@@ -609,23 +609,13 @@ static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 
 unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name)
 {
-       struct pci_dev *isa;
        unsigned long fixdma_base = dev->resource[4].start;
        byte tmpbyte;
        unsigned long flags;
 
        pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
 
-       for (isa = pci_devices; isa; isa=isa->next) {
-               /*
-                * look for ISA bridge
-                */
-               if (isa->vendor == PCI_VENDOR_ID_AL &&
-                   isa->device == PCI_DEVICE_ID_AL_M1533) {
-                       isa_dev = isa;
-                       break;
-               }
-       }
+       isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 
        if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) {
                /*
index b47904cdbc644edb1163ee563669eff8cb0259a2..3b446b43993e437449d85c9e1a0393a65439d5e4 100644 (file)
@@ -1559,10 +1559,6 @@ static int invalidate_drive(kdev_t rdev)
 static int fd_ioctl(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long param)
 {
-#define IOCTL_MODE_BIT 8
-#define OPEN_WRITE_BIT 16
-#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
-
        int drive, type;
        kdev_t device;
        struct atari_format_descr fmt_desc;
@@ -1616,8 +1612,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
                        return -EFAULT;
                return 0;
        }
-       if (!IOCTL_ALLOWED)
-               return -EPERM;
        switch (cmd) {
        case FDSETPRM:
        case FDDEFPRM:
@@ -1928,12 +1922,6 @@ static int floppy_open( struct inode *inode, struct file *filp )
        if (old_dev && old_dev != MINOR(inode->i_rdev))
                invalidate_buffers(MKDEV(FLOPPY_MAJOR, old_dev));
 
-       /* Allow ioctls if we have write-permissions even if read-only open */
-       if (filp->f_mode & 2 || permission (inode, 2) == 0)
-               filp->f_mode |= IOCTL_MODE_BIT;
-       if (filp->f_mode & 2)
-               filp->f_mode |= OPEN_WRITE_BIT;
-
        if (filp->f_flags & O_NDELAY)
                return 0;
 
@@ -1957,14 +1945,7 @@ static int floppy_release( struct inode * inode, struct file * filp )
 
        drive = MINOR(inode->i_rdev) & 3;
 
-       /*
-        * If filp is NULL, we're being called from blkdev_release
-        * or after a failed mount attempt.  In the former case the
-        * device has already been sync'ed, and in the latter no
-        * sync is required.  Otherwise, sync if filp is writable.
-        */
-       if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
-               block_fsync (filp, filp->f_dentry);
+       block_fsync (filp, filp->f_dentry);
 
        if (fd_ref[drive] < 0)
                fd_ref[drive] = 0;
index 24dd21c3a8aaca5350ce0bcb15c1c2b32d3072c0..3698a579cc2589f2519c0e7d1da37ece07b5075c 100644 (file)
@@ -3387,9 +3387,6 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                    unsigned long param)
 {
-#define IOCTL_MODE_BIT 8
-#define OPEN_WRITE_BIT 16
-#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
 #define OUT(c,x) case c: outparam = (const char *) (x); break
 #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
 
@@ -3457,8 +3454,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                return -EINVAL;
 
        /* permission checks */
-       if (((cmd & 0x40) && !IOCTL_ALLOWED) ||
-           ((cmd & 0x80) && !suser()))
+       if ((cmd & 0x80) && !suser())
                return -EPERM;
 
        /* copyin */
@@ -3578,7 +3574,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                return fd_copyout((void *)param, outparam, size);
        else
                return 0;
-#undef IOCTL_ALLOWED
 #undef OUT
 #undef IN
 }
@@ -3630,53 +3625,13 @@ static void config_types(void)
                printk("\n");
 }
 
-static ssize_t floppy_read(struct file * filp, char *buf,
-                          size_t count, loff_t *ppos)
-{
-       struct inode *inode = filp->f_dentry->d_inode;
-       int drive = DRIVE(inode->i_rdev);
-
-       check_disk_change(inode->i_rdev);
-       if (UTESTF(FD_DISK_CHANGED))
-               return -ENXIO;
-       return block_read(filp, buf, count, ppos);
-}
-
-static ssize_t floppy_write(struct file * filp, const char * buf,
-                           size_t count, loff_t *ppos)
-{
-       struct inode * inode = filp->f_dentry->d_inode;
-       int block;
-       int ret;
-       int drive = DRIVE(inode->i_rdev);
-
-       if (!UDRS->maxblock)
-               UDRS->maxblock=1;/* make change detectable */
-       check_disk_change(inode->i_rdev);
-       if (UTESTF(FD_DISK_CHANGED))
-               return -ENXIO;
-       if (!UTESTF(FD_DISK_WRITABLE))
-               return -EROFS;
-       block = (*ppos + count) >> 9;
-       INFBOUND(UDRS->maxblock, block);
-       ret= block_write(filp, buf, count, ppos);
-       return ret;
-}
-
 static int floppy_release(struct inode * inode, struct file * filp)
 {
        int drive;
 
        drive = DRIVE(inode->i_rdev);
 
-       /*
-        * If filp is NULL, we're being called from blkdev_release
-        * or after a failed mount attempt.  In the former case the
-        * device has already been sync'ed, and in the latter no
-        * sync is required.  Otherwise, sync if filp is writable.
-        */
-       if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
-               block_fsync(filp, filp->f_dentry);
+       block_fsync(filp, filp->f_dentry);
 
        if (UDRS->fd_ref < 0)
                UDRS->fd_ref=0;
@@ -3774,12 +3729,6 @@ static int floppy_open(struct inode * inode, struct file * filp)
                invalidate_buffers(MKDEV(FLOPPY_MAJOR,old_dev));
        }
 
-       /* Allow ioctls if we have write-permissions even if read-only open */
-       if ((filp->f_mode & 2) || (permission(inode,2) == 0))
-               filp->f_mode |= IOCTL_MODE_BIT;
-       if (filp->f_mode & 2)
-               filp->f_mode |= OPEN_WRITE_BIT;
-
        if (UFDCS->rawcmd == 1)
                UFDCS->rawcmd = 2;
 
@@ -3880,8 +3829,8 @@ static int floppy_revalidate(kdev_t dev)
 
 static struct file_operations floppy_fops = {
        NULL,                   /* lseek - default */
-       floppy_read,            /* read - general block-dev read */
-       floppy_write,           /* write - general block-dev write */
+       block_read,             /* read - general block-dev read */
+       block_write,            /* write - general block-dev write */
        NULL,                   /* readdir - bad */
        NULL,                   /* poll */
        fd_ioctl,               /* ioctl */
index 7a324759b46818ad9840cb2bc6f0444cee893b3c..5823e1b0d000f6541ca0757a74555758ae7c046f 100644 (file)
@@ -635,7 +635,7 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
        if (PCI_FUNC(dev->devfn) & 1)
                return;
        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
-       for (findev=pci_devices; findev; findev=findev->next) {
+       pci_for_each_dev(findev) {
                if ((findev->vendor == dev->vendor) &&
                    (findev->device == dev->device) &&
                    ((findev->devfn - dev->devfn) == 1) &&
@@ -669,9 +669,7 @@ void __init ide_scan_pcibus (void)
        ide_pci_devid_t         devid;
        ide_pci_device_t        *d;
 
-       if (!pci_present())
-               return;
-       for(dev = pci_devices; dev; dev=dev->next) {
+       pci_for_each_dev(dev) {
                devid.vid = dev->vendor;
                devid.did = dev->device;
                for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d);
index a950172ff2e8e30428105229758cf43a07677899..eec0e1663327a4fee7e52aff4568e54e85064d11 100644 (file)
@@ -375,7 +375,10 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
        }
 
        if (S_ISBLK(inode->i_mode)) {
-               error = blkdev_open(inode, file);
+               /* dentry will be wired, so... */
+               error = blkdev_get(inode->i_bdev, file->f_mode,
+                                  file->f_flags, BDEV_FILE);
+
                lo->lo_device = inode->i_rdev;
                lo->lo_flags = 0;
 
@@ -482,7 +485,8 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
                return -EBUSY;
 
        if (S_ISBLK(dentry->d_inode->i_mode))
-               blkdev_release (dentry->d_inode);
+               blkdev_put(dentry->d_inode->i_bdev, BDEV_FILE);
+
        lo->lo_dentry = NULL;
 
        if (lo->lo_backing_file != NULL) {
index 06cd279af91b7ffe9510851e0e2ac8687ccc3dcd..13aa88f6dc6de99c1713fb98a7df48efcb57a387 100644 (file)
@@ -250,9 +250,6 @@ static int floppy_revalidate(kdev_t dev);
 static int swim3_add_device(struct device_node *swims);
 int swim3_init(void);
 
-#define IOCTL_MODE_BIT 8
-#define OPEN_WRITE_BIT 16
-
 static void swim3_select(struct floppy_state *fs, int sel)
 {
        volatile struct swim3 *sw = fs->swim3;
@@ -821,8 +818,7 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
        if (devnum >= floppy_count)
                return -ENODEV;
                
-       if (((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT))) ||
-           ((cmd & 0x80) && !suser()))
+       if ((cmd & 0x80) && !suser())
                return -EPERM;
 
        fs = &floppy_states[devnum];
@@ -916,12 +912,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
        else
                ++fs->ref_count;
 
-       /* Allow ioctls if we have write-permissions even if read-only open */
-       if ((filp->f_mode & 2) || (permission(inode, 2) == 0))
-               filp->f_mode |= IOCTL_MODE_BIT;
-       if (filp->f_mode & 2)
-               filp->f_mode |= OPEN_WRITE_BIT;
-
        return 0;
 }
 
@@ -934,14 +924,7 @@ static int floppy_release(struct inode *inode, struct file *filp)
        if (devnum >= floppy_count)
                return -ENODEV;
 
-       /*
-        * If filp is NULL, we're being called from blkdev_release
-        * or after a failed mount attempt.  In the former case the
-        * device has already been sync'ed, and in the latter no
-        * sync is required.  Otherwise, sync if filp is writable.
-        */
-       if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
-               block_fsync (filp, filp->f_dentry);
+       block_fsync (filp, filp->f_dentry);
 
        fs = &floppy_states[devnum];
        sw = fs->swim3;
index f15f590a4255ee4edc5b1d581c27eb96d0b88735..8833d161b0b35f793d4c114167272e39ee0ae636 100644 (file)
@@ -45,9 +45,6 @@
 
 #define MAX_FLOPPIES   4
 
-#define IOCTL_MODE_BIT 8
-#define OPEN_WRITE_BIT 16
-
 enum swim_state {
        idle,
        available,
@@ -397,8 +394,7 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
        if (devnum >= floppy_count)
                return -ENODEV;
                
-       if (((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT))) ||
-           ((cmd & 0x80) && !suser()))
+       if ((cmd & 0x80) && !suser())
                return -EPERM;
 
        fs = &floppy_states[devnum];
@@ -451,12 +447,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
        else
                ++fs->ref_count;
 
-       /* Allow ioctls if we have write-permissions even if read-only open */
-       if ((filp->f_mode & 2) || (permission(inode, 2) == 0))
-               filp->f_mode |= IOCTL_MODE_BIT;
-       if (filp->f_mode & 2)
-               filp->f_mode |= OPEN_WRITE_BIT;
-
        return 0;
 }
 
@@ -468,14 +458,7 @@ static int floppy_release(struct inode *inode, struct file *filp)
        if (devnum >= floppy_count)
                return -ENODEV;
 
-       /*
-        * If filp is NULL, we're being called from blkdev_release
-        * or after a failed mount attempt.  In the former case the
-        * device has already been sync'ed, and in the latter no
-        * sync is required.  Otherwise, sync if filp is writable.
-        */
-       if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT)))
-               block_fsync (filp, filp->f_dentry);
+       block_fsync (filp, filp->f_dentry);
 
        fs = &floppy_states[devnum];
        if (fs->ref_count > 0) fs->ref_count--;
index 71e18e26992f61a5da6fd59572654b6c35c65ac6..12a1211527b03f3246e4bf2d32182fcb82fc1689 100644 (file)
@@ -2,7 +2,7 @@
  * linux/drivers/block/via82cxxx.c     Version 0.06    Dec. 13, 1999
  *
  *  Copyright (C) 1998-99 Michel Aubry, Maintainer
- *  Copyright (C) 1999 Jeff Garzik, MVP4 Support (jgarzik@pobox.com)
+ *  Copyright (C) 1999 Jeff Garzik, MVP4 Support (jgarzik@mandrakesoft.com)
  *  Copyright (C) 1998-99 Andre Hedrick (andre@suse.com)
  *  May be copied or modified under the terms of the GNU General Public License
  *
index 54ad294e7dd92292b6104e6de5cbd6bdb64cfa1e..e098b4bab3eb1d61fd4ba026f6718419b9228f97 100644 (file)
@@ -1094,5 +1094,6 @@ int agp_frontend_initialize(void)
 
 void agp_frontend_cleanup(void)
 {
+       misc_deregister(&agp_miscdev);
        return;
 }
index 623ac990835b45ef2d2c1d6aeb1682893ad4c68b..379a7b9299e9f24867a5d1e4e19872e898601c03 100644 (file)
@@ -3465,13 +3465,12 @@ int configure_bt848(struct pci_dev *dev, int bttv_num)
 
 static int find_bt848(void)
 {
-        struct pci_dev *dev = pci_devices;
+        struct pci_dev *dev;
         int result=0;
 
         bttv_num=0;
 
-        while (dev)
-        {
+       pci_for_each_dev(dev) {
                 if (dev->vendor == PCI_VENDOR_ID_BROOKTREE)
                         if ((dev->device == PCI_DEVICE_ID_BT848)||
                             (dev->device == PCI_DEVICE_ID_BT849)||
@@ -3480,7 +3479,6 @@ static int find_bt848(void)
                                 result=configure_bt848(dev,bttv_num++);
                 if (result)
                         return result;
-                dev = dev->next;
         }
        if(bttv_num)
                printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
index d97304a1369c5cfd5d96564c845ee5660b3be8a3..31fe71317e51f66d2946ea0ba63447b167747d6e 100644 (file)
@@ -1936,7 +1936,7 @@ static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
        /* Alternative: return sum of all words? */
 }
 
-#if 0  /* May be needed for IPv6 */
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
 {
@@ -2001,6 +2001,59 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
 #define REKEY_INTERVAL 300
 #define HASH_BITS 24
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+__u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
+                                  __u16 sport, __u16 dport)
+{
+       static __u32    rekey_time = 0;
+       static __u32    count = 0;
+       static __u32    secret[12];
+       struct timeval  tv;
+       __u32           seq;
+
+       /* The procedure is the same as for IPv4, but addresses are longer. */
+
+       do_gettimeofday(&tv);   /* We need the usecs below... */
+
+       if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
+               rekey_time = tv.tv_sec;
+               /* First five words are overwritten below. */
+               get_random_bytes(&secret[5], sizeof(secret)-5*4);
+               count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS;
+       }
+
+       memcpy(secret, saddr, 16);
+       secret[4]=(sport << 16) + dport;
+
+       seq = (twothirdsMD4Transform(daddr, secret) &
+              ((1<<HASH_BITS)-1)) + count;
+
+       seq += tv.tv_usec + tv.tv_sec*1000000;
+       return seq;
+}
+
+__u32 secure_ipv6_id(__u32 *daddr)
+{
+       static time_t   rekey_time = 0;
+       static __u32    secret[12];
+       time_t          t;
+
+       /*
+        * Pick a random secret every REKEY_INTERVAL seconds.
+        */
+       t = CURRENT_TIME;
+       if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
+               rekey_time = t;
+               /* First word is overwritten below. */
+               get_random_bytes(secret, sizeof(secret));
+       }
+
+       return twothirdsMD4Transform(daddr, secret);
+}
+
+#endif
+
+
 __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
                                 __u16 sport, __u16 dport)
 {
@@ -2054,6 +2107,38 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
        return seq;
 }
 
+/*  The code below is shamelessly stolen from secure_tcp_sequence_number().
+ *  All blames to Andrey V. Savochkin <saw@msu.ru>.
+ */
+__u32 secure_ip_id(__u32 daddr)
+{
+       static time_t   rekey_time = 0;
+       static __u32    secret[12];
+       time_t          t;
+
+       /*
+        * Pick a random secret every REKEY_INTERVAL seconds.
+        */
+       t = CURRENT_TIME;
+       if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
+               rekey_time = t;
+               /* First word is overwritten below. */
+               get_random_bytes(secret+1, sizeof(secret)-4);
+       }
+
+       /*
+        *  Pick a unique starting offset for each IP destination.
+        *  Note that the words are placed into the first words to be
+        *  mixed in with the halfMD4.  This is because the starting
+        *  vector is also a random secret (at secret+8), and further
+        *  hashing fixed data into it isn't going to improve anything,
+        *  so we should get started with the variable data.
+        */
+       secret[0]=daddr;
+
+       return halfMD4Transform(secret+8, secret);
+}
+
 #ifdef CONFIG_SYN_COOKIES
 /*
  * Secure SYN cookie computation. This is the algorithm worked out by
index 365c5bd3810893f90dd6f9825890847860c3b9b7..a0b2d89c6260b1eea96b64706daeea0ccdbe4ca3 100644 (file)
 
 #define dprintk(x...) 
 
-static kdev_t raw_device_bindings[256] = {};
+static struct block_device *raw_device_bindings[256] = {};
 static int raw_device_inuse[256] = {};
 static int raw_device_sector_size[256] = {};
 static int raw_device_sector_bits[256] = {};
 
-extern struct file_operations * get_blkfops(unsigned int major);
-
 static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);
 
 ssize_t        raw_read(struct file *, char *, size_t, loff_t *);
@@ -62,64 +60,11 @@ static struct file_operations raw_ctl_fops = {
        NULL            /* fsync */
 };
 
-
-
 void __init raw_init(void)
 {
        register_chrdev(RAW_MAJOR, "raw", &raw_fops);
 }
 
-
-/*
- * The raw IO open and release code needs to fake appropriate
- * open/release calls to the underlying block devices.  
- */
-
-static int bdev_open(kdev_t dev, int mode)
-{
-       int err = 0;
-       struct file dummy_file = {};
-       struct dentry dummy_dentry = {};
-       struct inode * inode = get_empty_inode();
-       
-       if (!inode)
-               return -ENOMEM;
-       
-       dummy_file.f_op = get_blkfops(MAJOR(dev));
-       if (!dummy_file.f_op) {
-               err = -ENODEV;
-               goto done;
-       }
-       
-       if (dummy_file.f_op->open) {
-               inode->i_rdev = dev;
-               dummy_dentry.d_inode = inode;
-               dummy_file.f_dentry = &dummy_dentry;
-               dummy_file.f_mode = mode;
-               err = dummy_file.f_op->open(inode, &dummy_file);
-       }
-
- done:
-       iput(inode);
-       return err;
-}
-
-static int bdev_close(kdev_t dev)
-{
-       int err;
-       struct inode * inode = get_empty_inode();
-
-       if (!inode)
-               return -ENOMEM;
-       
-       inode->i_rdev = dev;
-       err = blkdev_release(inode);
-       iput(inode);
-       return err;
-}
-
-
-
 /* 
  * Open/close code for raw IO.
  */
@@ -127,7 +72,8 @@ static int bdev_close(kdev_t dev)
 int raw_open(struct inode *inode, struct file *filp)
 {
        int minor;
-       kdev_t bdev;
+       struct block_device * bdev;
+       kdev_t rdev;    /* it should eventually go away */
        int err;
        int sector_size;
        int sector_bits;
@@ -150,10 +96,11 @@ int raw_open(struct inode *inode, struct file *filp)
         */
 
        bdev = raw_device_bindings[minor];
-       if (bdev == NODEV) 
+       if (!bdev)
                return -ENODEV;
 
-       err = bdev_open(bdev, filp->f_mode);
+       rdev = to_kdev_t(bdev->bd_dev);
+       err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
        if (err)
                return err;
        
@@ -171,15 +118,15 @@ int raw_open(struct inode *inode, struct file *filp)
         */
        
        sector_size = 512;
-       if (lookup_vfsmnt(bdev) != NULL) {
-               if (blksize_size[MAJOR(bdev)])
-                       sector_size = blksize_size[MAJOR(bdev)][MINOR(bdev)];
+       if (lookup_vfsmnt(rdev) != NULL) {
+               if (blksize_size[MAJOR(rdev)])
+                       sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
        } else {
-               if (hardsect_size[MAJOR(bdev)])
-                       sector_size = hardsect_size[MAJOR(bdev)][MINOR(bdev)];
+               if (hardsect_size[MAJOR(rdev)])
+                       sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)];
        }
 
-       set_blocksize(bdev, sector_size);
+       set_blocksize(rdev, sector_size);
        raw_device_sector_size[minor] = sector_size;
 
        for (sector_bits = 0; !(sector_size & 1); )
@@ -192,11 +139,11 @@ int raw_open(struct inode *inode, struct file *filp)
 int raw_release(struct inode *inode, struct file *filp)
 {
        int minor;
-       kdev_t bdev;
+       struct block_device *bdev;
        
        minor = MINOR(inode->i_rdev);
        bdev = raw_device_bindings[minor];
-       bdev_close(bdev);
+       blkdev_put(bdev, BDEV_RAW);
        raw_device_inuse[minor]--;
        return 0;
 }
@@ -261,11 +208,14 @@ int raw_ctl_ioctl(struct inode *inode,
                                err = -EBUSY;
                                break;
                        }
+                       if (raw_device_bindings[minor])
+                               bdput(raw_device_bindings[minor]);
                        raw_device_bindings[minor] = 
-                               MKDEV(rq.block_major, rq.block_minor);
+                               bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));
                } else {
-                       rq.block_major = MAJOR(raw_device_bindings[minor]);
-                       rq.block_minor = MINOR(raw_device_bindings[minor]);
+                       kdev_t dev=to_kdev_t(raw_device_bindings[minor]->bd_dev);
+                       rq.block_major = MAJOR(dev);
+                       rq.block_minor = MINOR(dev);
                        err = copy_to_user((void *) arg, &rq, sizeof(rq));
                }
                break;
@@ -317,7 +267,7 @@ ssize_t     rw_raw_dev(int rw, struct file *filp, char *buf,
         */
 
        minor = MINOR(filp->f_dentry->d_inode->i_rdev);
-       dev = raw_device_bindings[minor];
+       dev = to_kdev_t(raw_device_bindings[minor]->bd_dev);
        sector_size = raw_device_sector_size[minor];
        sector_bits = raw_device_sector_bits[minor];
        sector_mask = sector_size- 1;
index 04760928057a301d9b985634126c9bd61bc44b75..8fcbf00a01e5d11d5329f22faced14ccd5c42de2 100644 (file)
@@ -3990,7 +3990,6 @@ static struct pci_board pci_boards[] = {
  */
 static void probe_serial_pci(void) 
 {
-       u16 subvendor, subdevice;
        int k, line;
        struct pci_dev *dev = NULL;
        struct pci_board *board;
@@ -4002,18 +4001,7 @@ static void probe_serial_pci(void)
        printk(KERN_DEBUG "Entered probe_serial_pci()\n");
 #endif
   
-       if (!pcibios_present()) {
-#ifdef SERIAL_DEBUG_PCI
-               printk(KERN_DEBUG "Leaving probe_serial_pci() (no pcibios)\n");
-#endif
-               return;
-       }
-
-       for(dev=pci_devices; dev; dev=dev->next) {
-               pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID,
-                                        &subvendor);
-               pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &subdevice);
-
+       pci_for_each_dev(dev) {
                for (board = pci_boards; board->vendor; board++) {
                        if (board->vendor != (unsigned short) PCI_ANY_ID &&
                            dev->vendor != board->vendor)
@@ -4022,10 +4010,10 @@ static void probe_serial_pci(void)
                            dev->device != board->device)
                                continue;
                        if (board->subvendor != (unsigned short) PCI_ANY_ID &&
-                           subvendor != board->subvendor)
+                           dev->subsystem_vendor != board->subvendor)
                                continue;
                        if (board->subdevice != (unsigned short) PCI_ANY_ID &&
-                           subdevice != board->subdevice)
+                           dev->subsystem_device != board->subdevice)
                                continue;
                        break;
                }
index e000742bf1f8be55fe30e95afedc0e798fa2d93b..a34c85d1f6578de1029f7ee7a226c134545a0de0 100644 (file)
@@ -2243,26 +2243,19 @@ int init_module(void)
 int init_stradis_cards(struct video_init *unused)
 {
 #endif
-       struct pci_dev *dev = pci_devices;
+       struct pci_dev *dev = NULL;
        int result = 0, i;
-       u32 newcard;
 
        saa_num = 0;
 
-       while (dev) {
-               if (dev->vendor == PCI_VENDOR_ID_PHILIPS)
-                       if (dev->device == PCI_DEVICE_ID_PHILIPS_SAA7146) {
-                               pci_read_config_dword(dev,
-                                       PCI_SUBSYSTEM_VENDOR_ID, &newcard);
-                               if (!newcard)
-                                       printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num);
-                               else
-                                       printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); 
-                               result = configure_saa7146(dev, saa_num++);
-                       }
+       while ((dev = pci_find_device(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, dev))) {
+               if (!dev->subsystem_vendor_id)
+                       printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num);
+               else
+                       printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); 
+               result = configure_saa7146(dev, saa_num++);
                if (result)
                        return result;
-               dev = dev->next;
        }
        if (saa_num)
                printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num);
index d44f801df0bdfab41ffd92d62acc28ab1bdc4e65..c57bd390d3b1a953986645184b2d0bf2eebf44fe 100644 (file)
@@ -229,9 +229,8 @@ int __init i2o_pci_scan(void)
        int count=0;
        
        printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
-       
-       for(dev=pci_devices; dev!=NULL; dev=dev->next)
-       {
+
+       pci_for_each_dev(dev) {
                if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O)
                        continue;
                if((dev->class&0xFF)>1)
index b50a115a4e91a0bed815436edc352a7fb85af702..bf195f9f5b2aa89ee2b19c2cb8cedec0ec46136b 100644 (file)
@@ -1047,8 +1047,9 @@ pbook_pci_save(void)
        struct pci_save *ps;
 
        npci = 0;
-       for (pd = pci_devices; pd != NULL; pd = pd->next)
+       pci_for_each_dev(pd) {
                ++npci;
+       }
        n_pbook_pci_saves = npci;
        if (npci == 0)
                return;
@@ -1057,13 +1058,12 @@ pbook_pci_save(void)
        if (ps == NULL)
                return;
 
-       for (pd = pci_devices; pd != NULL && npci != 0; pd = pd->next) {
+       pci_for_each_dev(pd) {
                pci_read_config_word(pd, PCI_COMMAND, &ps->command);
                pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
                pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
                pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address);
                ++ps;
-               --npci;
        }
 }
 
@@ -1071,11 +1071,12 @@ static void __openfirmware
 pbook_pci_restore(void)
 {
        u16 cmd;
-       struct pci_save *ps = pbook_pci_saves;
+       struct pci_save *ps = pbook_pci_saves - 1;
        struct pci_dev *pd;
        int j;
 
-       for (pd = pci_devices; pd != NULL; pd = pd->next, ++ps) {
+       pci_for_each_dev(pd) {
+               ps++;
                if (ps->command == 0)
                        continue;
                pci_read_config_word(pd, PCI_COMMAND, &cmd);
index c282db8d95ef656ac971a005f44be769b7c97957..da372be1f74f34017c9f5d40208bbcaa4bff6cfd 100644 (file)
@@ -2529,13 +2529,23 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
  * eg ifconfig 
  */
     int i;
-    dev_link_t *link = dev_list;
-    struct net_device *dev = (struct net_device *)link->priv;
-    ray_dev_t *local = (ray_dev_t *)dev->priv;
+    dev_link_t *link;
+    struct net_device *dev;
+    ray_dev_t *local;
     UCHAR *p;
     struct freq_hop_element *pfh;
     UCHAR c[33];
 
+    link = dev_list;
+    if (!link)
+       return 0;
+    dev = (struct net_device *)link->priv;
+    if (!dev)
+       return 0;
+    local = (ray_dev_t *)dev->priv;
+    if (!local)
+       return 0;
+
     len = 0;
 
     len += sprintf(buf + len, "Raylink Wireless LAN driver status\n");
@@ -2663,7 +2673,59 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
     }
     return 0;
 } /* End build_auth_frame */
+
 /*===========================================================================*/
+
+static void raycs_write(const char *name, write_proc_t *w, void *data)
+{
+       struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL);
+       if (entry) {
+               entry->write_proc = w;
+               entry->data = data;
+       }
+}
+
+static int write_essid(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+       static char proc_essid[33];
+       int len = count;
+
+       if (len > 32)
+               len = 32;
+       memset(proc_essid, 0, 33);
+       if (copy_from_user(proc_essid, buffer, len))
+               return -EFAULT;
+       essid = proc_essid;
+       return count;
+}
+
+static int write_int(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+       static char proc_number[10];
+       char *p;
+       int nr, len;
+
+       if (!count)
+               return 0;
+
+       if (count > 9)
+               return -EINVAL;
+       if (copy_from_user(proc_number, buffer, count))
+               return -EFAULT;
+       p = proc_number;
+       nr = 0;
+       len = count;
+       do {
+               unsigned int c = *p - '0';
+               if (c > 9)
+                       return -EINVAL;
+               nr = nr*10 + c;
+               p++;
+       } while (--len);
+       *(int *)data = nr;
+       return count;
+}
+
 static int __init init_ray_cs(void)
 {
     int rc;
@@ -2671,41 +2733,35 @@ static int __init init_ray_cs(void)
     DEBUG(1, "%s\n", rcsid);
     rc = register_pcmcia_driver(&dev_info, &ray_attach, &ray_detach);
     DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc);
-#ifdef CONFIG_PROC_FS    
-    /* [proc-namespace][fixme] It shouldn't be under root, damnit! */
-    create_proc_info_entry("ray_cs", 0, &proc_root, ray_cs_proc_read);
-#endif    
+
+    proc_mkdir("driver/ray_cs", 0);
+
+    create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, ray_cs_proc_read);
+    raycs_write("driver/ray_cs/essid", write_essid, NULL);
+    raycs_write("driver/ray_cs/net_type", write_int, &net_type);
+    raycs_write("driver/ray_cs/translate", write_int, &translate);
     if (translate != 0) translate = 1;
     return 0;
 } /* init_ray_cs */
 
-#ifndef MODULE
-
-static char init_ess_id[ESSID_SIZE];
-static int __init essid_setup(char *str)
-{
-       strncpy(init_ess_id, str, ESSID_SIZE);
-       essid = init_ess_id;
-       return 1;
-}
-__setup("essid=", essid_setup);
-
-#endif
-
 /*===========================================================================*/
 
 static void __exit exit_ray_cs(void)
 {
     DEBUG(0, "ray_cs: cleanup_module\n");
 
+
+    remove_proc_entry("ray_cs", proc_root_driver);
     unregister_pcmcia_driver(&dev_info);
     while (dev_list != NULL) {
         if (dev_list->state & DEV_CONFIG) ray_release((u_long)dev_list);
         ray_detach(dev_list);
     }
-#ifdef CONFIG_PROC_FS    
-    remove_proc_entry("ray_cs", &proc_root);
-#endif   
+    remove_proc_entry("driver/ray_cs/ray_cs", NULL);
+    remove_proc_entry("driver/ray_cs/essid", NULL);
+    remove_proc_entry("driver/ray_cs/net_type", NULL);
+    remove_proc_entry("driver/ray_cs/translate", NULL);
+    remove_proc_entry("driver/ray_cs", NULL);
 } /* exit_ray_cs */
 
 module_init(init_ray_cs);
index e7407fafc2b1186e7b97e3cafc0fb1ec76d7a1d5..eabffab8027d1cb5b97e11d4d8375fe4228722d5 100644 (file)
@@ -3324,10 +3324,10 @@ static void tulip_detach(dev_node_t *node)
        if (*devp) {
                struct net_device *dev = *devp;
                struct tulip_private *tp = dev->priv;
+               *devp = *next;
                unregister_netdev(dev);
                kfree(dev);
                kfree(tp);
-               *devp = *next;
                kfree(node);
                MOD_DEC_USE_COUNT;
        }
index 2eeccf71e5c8010b226fb329efb0face54c8c098..376d01d30daeb4fac3f83eb345bb1d9675d158fb 100644 (file)
@@ -1828,7 +1828,7 @@ static int __init parport_pc_init_pci (int irq, int dma)
        }
 
        /* Look for parallel controllers that we don't know about. */
-       for (pcidev = pci_devices; pcidev; pcidev = pcidev->next) {
+       pci_for_each_dev(pcidev) {
                const int class_noprogif = pcidev->class & ~0xff;
                if (class_noprogif != (PCI_CLASS_COMMUNICATION_PARALLEL << 8))
                        continue;
index 1b4cdec024b3f243953e84e8c5efd8c28d637e1b..f2cbdc910b674c18397a805a3016eb4b6f43fcc6 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     PCI Bus Services -- Function For Backward Compatibility
  *
- *     Copyright 1998, 1999 Martin Mares <mj@suse.cz>
+ *     Copyright 1998--2000 Martin Mares <mj@suse.cz>
  */
 
 #include <linux/types.h>
@@ -13,7 +13,7 @@
 int
 pcibios_present(void)
 {
-       return !!pci_devices;
+       return pci_devices.next != &pci_devices;
 }
 
 int
index c88481042da2e679b030176611f74975729515b4..cd21631e3d36918deb70e11ac4176a517564830a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * drivers/pci/helper.c
  *
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
  * This software is free.  See the file COPYING for licensing details.
  *
  */
index a3b741728e054717b140d9e70309343987b804c3..1f98f50de94da1ff284816cd9fc3656fbfecbc2c 100644 (file)
@@ -6,7 +6,7 @@
  *     Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
  *     David Mosberger-Tang
  *
- *     Copyright 1997 -- 1999 Martin Mares <mj@suse.cz>
+ *     Copyright 1997 -- 2000 Martin Mares <mj@suse.cz>
  */
 
 #include <linux/types.h>
 #define DBG(x...)
 #endif
 
-struct pci_bus *pci_root;
-struct pci_dev *pci_devices = NULL;
-static struct pci_dev **pci_last_dev_p = &pci_devices;
+LIST_HEAD(pci_root_buses);
+LIST_HEAD(pci_devices);
 
 struct pci_dev *
 pci_find_slot(unsigned int bus, unsigned int devfn)
 {
        struct pci_dev *dev;
 
-       for(dev=pci_devices; dev; dev=dev->next)
+       pci_for_each_dev(dev) {
                if (dev->bus->number == bus && dev->devfn == devfn)
-                       break;
-       return dev;
+                       return dev;
+       }
+       return NULL;
 }
 
 
@@ -48,20 +48,16 @@ pci_find_subsys(unsigned int vendor, unsigned int device,
                unsigned int ss_vendor, unsigned int ss_device,
                struct pci_dev *from)
 {
-       struct pci_dev *dev;
+       struct list_head *n = from ? from->global_list.next : pci_devices.next;
 
-       if (from)
-               dev = from->next;
-       else
-               dev = pci_devices;
-
-       while (dev) {
+       while (n != &pci_devices) {
+               struct pci_dev *dev = pci_dev_g(n);
                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
                    (device == PCI_ANY_ID || dev->device == device) &&
                    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
                    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
                        return dev;
-               dev = dev->next;
+               n = n->next;
        }
        return NULL;
 }
@@ -77,13 +73,15 @@ pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
 struct pci_dev *
 pci_find_class(unsigned int class, struct pci_dev *from)
 {
-       if (!from)
-               from = pci_devices;
-       else
-               from = from->next;
-       while (from && from->class != class)
-               from = from->next;
-       return from;
+       struct list_head *n = from ? from->global_list.next : pci_devices.next;
+
+       while (n != &pci_devices) {
+               struct pci_dev *dev = pci_dev_g(n);
+               if (dev->class == class)
+                       return dev;
+               n = n->next;
+       }
+       return NULL;
 }
 
 
@@ -412,6 +410,19 @@ void __init pci_read_bridge_bases(struct pci_bus *child)
        }
 }
 
+static struct pci_bus * __init pci_alloc_bus(void)
+{
+       struct pci_bus *b;
+
+       b = kmalloc(sizeof(*b), GFP_KERNEL);
+       if (b) {
+               memset(b, 0, sizeof(*b));
+               INIT_LIST_HEAD(&b->children);
+               INIT_LIST_HEAD(&b->devices);
+       }
+       return b;
+}
+
 static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 {
        struct pci_bus *child;
@@ -419,11 +430,9 @@ static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pc
        /*
         * Allocate a new bus, and inherit stuff from the parent..
         */
-       child = kmalloc(sizeof(*child), GFP_KERNEL);
-       memset(child, 0, sizeof(*child));
+       child = pci_alloc_bus();
 
-       child->next = parent->children;
-       parent->children = child;
+       list_add_tail(&child->node, &parent->children);
        child->self = dev;
        dev->subordinate = child;
        child->parent = parent;
@@ -455,6 +464,7 @@ static int __init pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int
        /*
         * Insert it into the tree of buses.
         */
+       DBG("Scanning CardBus bridge %s\n", dev->slot_name);
        child = pci_add_new_bus(bus, dev, ++busnr);
 
        for (i = 0; i < 4; i++)
@@ -517,6 +527,7 @@ static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int
        /*
         * Insert it into the tree of buses.
         */
+       DBG("Scanning behind PCI bridge %s\n", dev->slot_name);
        child = pci_add_new_bus(bus, dev, ++max);
        sprintf(child->name, "PCI Bus #%02x", child->number);
 
@@ -599,6 +610,8 @@ int pci_setup_device(struct pci_dev * dev)
        dev->class = class;
        class >>= 8;
 
+       DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type);
+
        switch (dev->hdr_type) {                    /* header type */
        case PCI_HEADER_TYPE_NORMAL:                /* standard header */
                if (class == PCI_CLASS_BRIDGE_PCI)
@@ -694,21 +707,12 @@ struct pci_dev * __init pci_scan_slot(struct pci_dev *temp)
                        first_dev = dev;
                }
 
-               DBG("PCI: %02x:%02x [%04x/%04x] %06x %02x\n", bus->number, dev->devfn, dev->vendor, dev->device, dev->class, hdr_type);
-
-               /*
-                * Put it into the global PCI device chain. It's used to
-                * find devices once everything is set up.
-                */
-               *pci_last_dev_p = dev;
-               pci_last_dev_p = &dev->next;
-
                /*
-                * Now insert it into the list of devices held
-                * by the parent bus.
+                * Link the device to both the global PCI device chain and
+                * the per-bus list of devices.
                 */
-               *bus->last_dev_p = dev;
-               bus->last_dev_p = &dev->sibling;
+               list_add_tail(&dev->global_list, &pci_devices);
+               list_add_tail(&dev->bus_list, &bus->devices);
 
                /* Fix up broken headers */
                pci_fixup_device(PCI_FIXUP_HEADER, dev);
@@ -719,10 +723,10 @@ struct pci_dev * __init pci_scan_slot(struct pci_dev *temp)
 static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
 {
        unsigned int devfn, max;
+       struct list_head *ln;
        struct pci_dev *dev, dev0;
 
-       DBG("pci_do_scan_bus for bus %d\n", bus->number);
-       bus->last_dev_p = &bus->devices;
+       DBG("Scanning bus %02x\n", bus->number);
        max = bus->secondary;
 
        /* Create a device template */
@@ -740,8 +744,10 @@ static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
         * After performing arch-dependent fixup of the bus, look behind
         * all PCI-to-PCI bridges on this bus.
         */
+       DBG("Fixups for bus %02x\n", bus->number);
        pcibios_fixup_bus(bus);
-       for (dev = bus->devices; dev; dev = dev->sibling) {
+       for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+               dev = pci_dev_b(ln);
                switch (dev->class >> 8) {
                case PCI_CLASS_BRIDGE_PCI:
                        max = pci_scan_bridge(bus, dev, max);
@@ -759,40 +765,34 @@ static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
         *
         * Return how far we've got finding sub-buses.
         */
-       DBG("PCI: pci_do_scan_bus returning with max=%02x\n", max);
+       DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max);
        return max;
 }
 
-static int __init pci_bus_exists(struct pci_bus *b, int nr)
+static int __init pci_bus_exists(struct list_head *list, int nr)
 {
-       while (b) {
-               if (b->number == nr)
-                       return 1;
-               if (b->children && pci_bus_exists(b->children, nr))
+       struct list_head *l;
+
+       for(l=list->next; l != list; l = l->next) {
+               struct pci_bus *b = pci_bus_b(l);
+               if (b->number == nr || pci_bus_exists(&b->children, nr))
                        return 1;
-               b = b->next;
        }
        return 0;
 }
 
 struct pci_bus * __init pci_alloc_primary_bus(int bus)
 {
-       struct pci_bus *b, **r;
+       struct pci_bus *b;
 
-       if (pci_bus_exists(pci_root, bus)) {
+       if (pci_bus_exists(&pci_root_buses, bus)) {
                /* If we already got to this bus through a different bridge, ignore it */
                DBG("PCI: Bus %02x already known\n", bus);
                return NULL;
        }
 
-       b = kmalloc(sizeof(*b), GFP_KERNEL);
-       memset(b, 0, sizeof(*b));
-
-       /* Put the new bus at the end of the chain of busses.  */
-       r = &pci_root;
-       while (*r)
-               r = &(*r)->next;
-       *r = b;
+       b = pci_alloc_bus();
+       list_add_tail(&b->node, &pci_root_buses);
 
        b->number = b->secondary = bus;
        b->resource[0] = &ioport_resource;
@@ -817,8 +817,9 @@ void __init pci_init(void)
 
        pcibios_init();
 
-       for(dev=pci_devices; dev; dev=dev->next)
+       pci_for_each_dev(dev) {
                pci_fixup_device(PCI_FIXUP_FINAL, dev);
+       }
 }
 
 static int __init pci_setup(char *str)
index 6b3e025faedae5dd34d1c58644e031b7d7309af8..07282c4bfea9b54a5708d156c6f21f5d13b7d390 100644 (file)
@@ -4,7 +4,7 @@
 #      Maintained by Martin Mares <pci-ids@ucw.cz>
 #      If you have any new entries, send them to the maintainer.
 #
-#      $Id: pci.ids,v 1.43 1999/12/04 12:32:55 mj Exp $
+#      $Id: pci.ids,v 1.46 2000/01/02 20:32:11 mj Exp $
 #
 
 # Vendors, devices and subsystems. Please keep sorted.
        0002  PT80C524 [Nile]
        0005  National PC87550 System Controller
        8002  PT80C524 [Nile]
-1067  Mitsubishi Electronics
+1067  Mitsubishi Electric
+       1002  VG500 [VolumePro Volume Rendering Accelerator]
 1068  Diversified Technology
 1069  Mylex Corporation
        0001  DAC960P
        0010  VME Bridge Model 618
        3000  VME Bridge Model 2706
 108c  Oakleigh Systems Inc.
-108d  Olicom
-       0001  OC-3136/3137
+108d Olicom
+       0001  Token-Ring 16/4 PCI Adapter (3136/3137)
        0002  16/4 Token Ring
-       0004  OC-3139/3140 RapidFire Token-Ring 16/4
-       0005  OC-3250 GoCard Token-Ring 16/4
+       0004  RapidFire 3139 Token-Ring 16/4 PCI Adapter
+       0005  GoCard 3250 Token-Ring 16/4 CardBus PC Card
        0006  OC-3530 RapidFire Token-Ring 100
-       0007  OC-3141 RapidFire Token-Ring 16/4
+       0007  RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter
+       0008  RapidFire 3540 HSTR 100/16/4 PCI Adapter
        0011  OC-2315
        0012  OC-2325
        0013  OC-2183/2185
        9080  9080
                10b5 9080  9080 [real subsystem ID not set]
 10b6  Madge Networks
-       0001  Smart 16/4 Ringnode
-       0002  Smart 16/4 BM Mk2 Ringnode
-       0003  Smart 16/4 Ringnode
-               0e11 b0fd  NC4621 4/16 Token-Ring Adapter + WOL
-               10b6 0003  Smart 16/4 Ringnode Mk3
-               10b6 0007  Presto Mk2
-       0004  Smart 16/4 Ringnode (BM)
+       0001  Smart 16/4 PCI Ringnode
+       0002  Smart 16/4 PCI Ringnode Mk2
+               10b6 0002  Smart 16/4 PCI Ringnode Mk2
+               10b6 0006  16/4 CardBus Adapter
+       0003  Smart 16/4 PCI Ringnode Mk3
+               0e11 b0fd  Compaq NC4621 PCI, 4/16, WOL
+               10b6 0003  Smart 16/4 PCI Ringnode Mk3
+               10b6 0007  Presto PCI Plus Adapter
+       0004  Smart 16/4 PCI Ringnode Mk1
        0006  16/4 Cardbus Adapter
-       0007  Presto
-       1000  Collage 25 ATM adaptor
-       1001  Collage 155 Server
+               10b6 0006  16/4 CardBus Adapter
+       0007  Presto PCI Adapter
+       0009  Smart 100/16/4 PCI-HS Ringnode
+       000a  Smart 100/16/4 PCI Ringnode
+       000b  16/4 CardBus Adapter Mk2
+       1000  Collage 25 ATM Adapter
+       1001  Collage 155 ATM Server Adapter
 10b7  3Com Corporation
        0001  3c985 1000BaseSX
        3390  Token Link Velocity
        8888  Cinemaster C 3.0 DVD Decoder
 1240  Marathon Technologies Corp.
 1241  DSC Communications
+1242  Jaycor Networks, Inc.
+       4643  FCI-1063 Fibre Channel Adapter
 1243  Delphax
 1244  AVM Audiovisuelles MKTG & Computer System GmbH
        0700  B1 ISDN
 12c4  Connect Tech Inc
 12c5  Picture Elements Incorporated
        0081  PCIVST [Grayscale Thresholding Engine]
-       0086  THR2 Thresholder
+       0085  Video Simulator/Sender
+       0086  THR2 Multi-scale Thresholder
 12c6  Mitani Corporation
 12c7  Dialogic Corp
 12c8  G Force Co, Ltd
                0e11 b123  NC1634 Gigabit Ethernet Adapter
                1014 0119  Netfinity Gigabit Ethernet SX Adapter
                8086 1000  EtherExpress PRO/1000 Gigabit Server Adapter
+       1030  82559 InBusiness 10/100
        1209  82559ER
        1221  82092AA_0
        1222  82092AA_1
index 3c9d1caaead01752ce1ae3f14e595258a5e1fa16..28adb8e8a9186ece86cd46ed1d895e53e6ec6279 100644 (file)
@@ -18,7 +18,7 @@ EXPORT_SYMBOL(pci_write_config_byte);
 EXPORT_SYMBOL(pci_write_config_word);
 EXPORT_SYMBOL(pci_write_config_dword);
 EXPORT_SYMBOL(pci_devices);
-EXPORT_SYMBOL(pci_root);
+EXPORT_SYMBOL(pci_root_buses);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pci_find_class);
 EXPORT_SYMBOL(pci_find_device);
@@ -27,6 +27,7 @@ EXPORT_SYMBOL(pci_set_master);
 EXPORT_SYMBOL(pci_simple_probe);
 EXPORT_SYMBOL(pci_set_power_state);
 EXPORT_SYMBOL(pci_assign_resource);
+EXPORT_SYMBOL(pci_setup_device);
 #ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_device);
index 56ca2b46a56e8946a2ef33272693a2de065ab7da..e2cb9e9d64c015f6dd6958eef879520c85f7a3ca 100644 (file)
@@ -218,12 +218,12 @@ static struct inode_operations proc_bus_pci_inode_operations = {
 static int
 get_pci_dev_info(char *buf, char **start, off_t pos, int count)
 {
-       struct pci_dev *dev = pci_devices;
+       struct pci_dev *dev;
        off_t at = 0;
        int len, i, cnt;
 
        cnt = 0;
-       while (dev && count > cnt) {
+       pci_for_each_dev(dev) {
                len = sprintf(buf, "%02x%02x\t%04x%04x\t%x",
                        dev->bus->number,
                        dev->devfn,
@@ -247,7 +247,6 @@ get_pci_dev_info(char *buf, char **start, off_t pos, int count)
                                cnt += len;
                        buf += len;
                }
-               dev = dev->next;
        }
        return (count > cnt) ? cnt : count;
 }
@@ -289,18 +288,6 @@ int pci_proc_detach_device(struct pci_dev *dev)
        return 0;
 }
 
-void __init proc_bus_pci_add(struct pci_bus *bus)
-{
-       while (bus) {
-               struct pci_dev *dev;
-
-               for(dev = bus->devices; dev; dev = dev->sibling)
-                       pci_proc_attach_device(dev);
-               if (bus->children)
-                       proc_bus_pci_add(bus->children);
-               bus = bus->next;
-       }
-}
 
 /*
  *  Backward compatible /proc/pci interface.
@@ -406,12 +393,15 @@ static int pci_read_proc(char *buf, char **start, off_t off,
        int nprinted, len, begin = 0;
        struct pci_dev *dev;
 
-       len   = sprintf(buf, "PCI devices found:\n");
+       len = sprintf(buf, "PCI devices found:\n");
 
-       for (dev = pci_devices; dev; dev = dev->next) {
+       *eof = 1;
+       pci_for_each_dev(dev) {
                nprinted = sprint_dev_config(dev, buf + len, count - len);
-               if (nprinted < 0)
+               if (nprinted < 0) {
+                       *eof = 0;
                        break;
+               }
                len += nprinted;
                if (len+begin < off) {
                        begin += len;
@@ -420,8 +410,6 @@ static int pci_read_proc(char *buf, char **start, off_t off,
                if (len+begin >= off+count)
                        break;
        }
-       if (!dev || len+begin < off)
-               *eof = 1;
        off -= begin;
        *start = buf + off;
        len -= off;
@@ -435,10 +423,13 @@ static int pci_read_proc(char *buf, char **start, off_t off,
 static int __init pci_proc_init(void)
 {
        if (pci_present()) {
+               struct pci_dev *dev;
                proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
                create_proc_info_entry("devices", 0, proc_bus_pci_dir,
                                        get_pci_dev_info);
-               proc_bus_pci_add(pci_root);
+               pci_for_each_dev(dev) {
+                       pci_proc_attach_device(dev);
+               }
                create_proc_read_entry("pci", 0, NULL, pci_read_proc, NULL);
        }
        return 0;
index 8c456fedcc96bb6ec68f06338a55839c1b8f05e3..bb4d3cf443480f1252eb76795aee2a498313d5c0 100644 (file)
@@ -144,8 +144,10 @@ void __init
 pci_assign_unassigned_resources(u32 min_io, u32 min_mem)
 {
        struct pci_dev *dev;
-       for (dev = pci_devices; dev; dev = dev->next)
+
+       pci_for_each_dev(dev) {
                pdev_assign_unassigned_resources(dev, min_io, min_mem);
+       }
 }
 
 #define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
@@ -157,14 +159,16 @@ pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
        struct pbus_set_ranges_data inner;
        struct pci_bus *child;
        struct pci_dev *dev;
+       struct list_node *ln;
 
        inner.found_vga = 0;
        inner.mem_start = inner.io_start = ~0UL;
        inner.mem_end = inner.io_end = 0;
 
        /* Collect information about how our direct children are layed out. */
-       for (dev = bus->devices; dev; dev = dev->sibling) {
+       for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
                int i;
+               dev = pci_dev_b(ln);
                for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                        struct resource *res = &dev->resource[i];
                        if (res->flags & IORESOURCE_IO) {
@@ -184,8 +188,8 @@ pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
        }
 
        /* And for all of the sub-busses.  */
-       for (child = bus->children; child; child = child->next)
-               pbus_set_ranges(child, &inner);
+       for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+               pbus_set_ranges(pci_bus_b(ln), &inner);
 
        /* Align the values.  */
        inner.io_start = ROUND_DOWN(inner.io_start, 4*1024);
@@ -271,9 +275,10 @@ pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
 void __init
 pci_set_bus_ranges(void)
 {
-       struct pci_bus *bus;
-       for (bus = pci_root; bus; bus = bus->next)
-               pbus_set_ranges(bus, NULL);
+       struct list_node *ln;
+
+       for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
+               pci_set_ranges(pci_bus_b(ln), NULL);
 }
 
 static void __init
@@ -315,8 +320,9 @@ pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
               int (*map_irq)(struct pci_dev *, u8, u8))
 {
        struct pci_dev *dev;
-       for (dev = pci_devices; dev; dev = dev->next)
+       pci_for_each_dev(dev) {
                pdev_fixup_irq(dev, swizzle, map_irq);
+       }
 }
 
 int
index 6b7dbf95e54cb08928b4faa26c3d7333a70e5664..4642ff91368989742530d341dcdaeed82c6277ad 100644 (file)
@@ -267,8 +267,8 @@ int cb_alloc(socket_info_t * s)
        bus = s->cap.cb_dev->subordinate;
        memset(&tmp, 0, sizeof(tmp));
        tmp.bus = bus;
+       tmp.sysdata = bus->sysdata;
        tmp.devfn = 0;
-       printk("bus=%p, number=%d\n", bus, bus->number);
 
        pci_readw(&tmp, PCI_VENDOR_ID, &vend);
        pci_readw(&tmp, PCI_DEVICE_ID, &dev);
@@ -280,8 +280,7 @@ int cb_alloc(socket_info_t * s)
        if (hdr & 0x80) {
                do {
                        tmp.devfn = fn;
-                       pci_readw(&tmp, PCI_VENDOR_ID, &v);
-                       if (v != vend)
+                       if (pci_readw(&tmp, PCI_VENDOR_ID, &v) || !v || v == 0xffff)
                                break;
                        fn++;
                } while (fn < 8);
@@ -298,15 +297,14 @@ int cb_alloc(socket_info_t * s)
                int r;
 
                dev->bus = bus;
+               dev->sysdata = bus->sysdata;
                dev->devfn = i;
-               if (i < fn - 1) {
-                       dev->sibling = dev->next = &c[i + 1].dev;
-               }
                dev->vendor = vend;
                pci_readw(dev, PCI_DEVICE_ID, &dev->device);
                dev->hdr_type = hdr;
 
                pci_setup_device(dev);
+               /* FIXME: Do we need to enable the expansion ROM? */
                for (r = 0; r < 7; r++) {
                        struct resource *res = dev->resource + r;
                        if (res->flags) {
@@ -321,19 +319,17 @@ int cb_alloc(socket_info_t * s)
                               res->end,
                               res->flags);
                }
-               pci_enable_device(dev);
 
+               list_add_tail(&dev->bus_list, &bus->devices);
+               list_add_tail(&dev->global_list, &pci_devices);
 #ifdef CONFIG_PROC_FS
                pci_proc_attach_device(dev);
 #endif
+
+               pci_enable_device(dev);
        }
 
-       /* Link into PCI device chain */
-       bus->devices = &c[0].dev;
-       c[fn - 1].dev.next = pci_devices;
-       pci_devices = &c[0].dev;
        s->cb_config = c;
-
        return CS_SUCCESS;
 }
 
@@ -351,25 +347,18 @@ static void free_resources(struct pci_dev *dev)
 void cb_free(socket_info_t * s)
 {
        cb_config_t *c = s->cb_config;
-       struct pci_bus *bus = s->cap.cb_dev->subordinate;
+       int i;
 
        if (c) {
-               struct pci_dev **p;
-               /* Unlink from PCI device chain */
-               p = &pci_devices;
-               while (*p) {
-                       struct pci_dev *dev = *p;
-                       if (dev->bus != bus) {
-                               p = &dev->next;
-                               continue;
-                       }
-                       *p = dev->next;
+               for(i=0; i<s->functions; i++) {
+                       struct pci_dev *dev = &c[i].dev;
+                       list_del(&dev->bus_list);
+                       list_del(&dev->global_list);
                        free_resources(dev);
 #ifdef CONFIG_PROC_FS
                        pci_proc_detach_device(dev);
 #endif
                }
-               bus->devices = NULL;
                kfree(s->cb_config);
                s->cb_config = NULL;
                printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
index c2413f526a36953f27cbfec20efee4a9f002d61f..3a4a94b74091d9c9b96b6cf40ed8546ebfcff81b 100644 (file)
@@ -428,13 +428,18 @@ static unsigned int yenta_probe_irq(pci_socket_t *socket)
 
        /* Are we set up to route the IO irq to the PCI irq? */
        bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
-       if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
-               socket->io_irq = socket->cb_irq;
-               if (socket->cb_irq && socket->cb_irq < 16)
-                       return 1 << socket->cb_irq;
+       if (socket->cb_irq) {
+               if (bridge_ctrl & CB_BRIDGE_INTR) {
+                       bridge_ctrl &= ~CB_BRIDGE_INTR;
+                       config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
+               }
+               printk("CardBus: using PCI interrupt %d\n", socket->cb_irq);
+               return 1 << socket->cb_irq;
+       }
 
-               /* Uhhuh. Try falling back on ISA interrupts */
-               printk("CardBus: Hmm.. Bad PCI irq routing (irq%d)\n", socket->cb_irq);
+       /* Uhhuh. No PCI interrupt: try falling back on ISA interrupts */
+       printk("CardBus: Hmm.. No PCI irq routing (irq%d).\n", socket->cb_irq);
+       if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
                bridge_ctrl |= CB_BRIDGE_INTR;
                config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
        }
@@ -558,8 +563,6 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
        offset = 0x1c + 8*nr;
        bus = socket->dev->subordinate;
        res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
-       printk("dev=%p, bus=%p, parent=%p\n", socket->dev, bus, socket->dev->bus);
-       printk("res = %p, bus->res = %p\n", res, bus->resource[nr]);
        res->name = bus->name;
        res->flags = type;
        res->start = 0;
index 3ec11f0922aac48a31233431414ebc2684997a32..5d99f4c992368681e354e5dfe2f8c198f4438902 100644 (file)
@@ -39,6 +39,9 @@
 #include <asm/uaccess.h>
 #include <linux/isapnp.h>
 
+LIST_HEAD(isapnp_cards);
+LIST_HEAD(isapnp_devices);
+
 #ifdef CONFIG_PROC_FS
 #include "isapnp_proc.c"
 #endif
@@ -108,9 +111,6 @@ MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s)
 #define _LTAG_MEM32RANGE       0x85
 #define _LTAG_FIXEDMEM32RANGE  0x86
 
-struct pci_bus *isapnp_cards = NULL;   /* ISA PnP cards */
-struct pci_dev *isapnp_devices = NULL; /* ISA PnP devices */
-static struct pci_dev *isapnp_last_device = NULL;
 static unsigned char isapnp_checksum_value;
 static DECLARE_MUTEX(isapnp_cfg_mutex);
 static int isapnp_detected = 0;
@@ -749,18 +749,13 @@ static int __init isapnp_create_device(struct pci_bus *card,
 {
        int number = 0, skip = 0, dependent = 0, compat = 0;
        unsigned char type, tmp[17];
-       struct pci_dev *dev, *prev_dev;
+       struct pci_dev *dev;
        struct isapnp_resources *res = NULL;
        
        if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
                return 1;
-       card->devices = dev;
-       if (isapnp_last_device) {
-               isapnp_last_device->next = dev;
-               isapnp_last_device = dev;
-       } else {
-               isapnp_devices = isapnp_last_device = dev;
-       }
+       list_add(&dev->bus_list, &card->devices);
+       list_add_tail(&dev->global_list, &isapnp_devices);
        while (1) {
                if (isapnp_read_tag(&type, &size)<0)
                        return 1;
@@ -769,13 +764,11 @@ static int __init isapnp_create_device(struct pci_bus *card,
                switch (type) {
                case _STAG_LOGDEVID:
                        if (size >= 5 && size <= 6) {
-                               prev_dev = dev;
                                isapnp_config_prepare(dev);
                                if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
                                        return 1;
-                               prev_dev->sibling = dev;
-                               isapnp_last_device->next = dev;
-                               isapnp_last_device = dev;
+                               list_add_tail(&dev->bus_list, &card->devices);
+                               list_add_tail(&dev->global_list, &isapnp_devices);
                                size = 0;
                                skip = 0;
                        } else {
@@ -970,7 +963,7 @@ static int __init isapnp_build_device_list(void)
 {
        int csn;
        unsigned char header[9], checksum;
-       struct pci_bus *card, *prev = NULL;
+       struct pci_bus *card;
 
        isapnp_wait();
        isapnp_key();
@@ -997,11 +990,8 @@ static int __init isapnp_build_device_list(void)
                if (isapnp_checksum_value != 0x00)
                        printk("isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
                card->checksum = isapnp_checksum_value;
-               if (!isapnp_cards)
-                       isapnp_cards = card;
-               else
-                       prev->next = card;
-               prev = card;
+
+               list_add_tail(&card->node, &isapnp_cards);
        }
        return 0;
 }
@@ -1012,9 +1002,7 @@ static int __init isapnp_build_device_list(void)
 
 int isapnp_present(void)
 {
-       if (isapnp_devices)
-               return 1;
-       return 0;
+       return !list_empty(&isapnp_devices);
 }
 
 int isapnp_cfg_begin(int csn, int logdev)
@@ -1152,16 +1140,17 @@ struct pci_bus *isapnp_find_card(unsigned short vendor,
                                 unsigned short device,
                                 struct pci_bus *from)
 {
-       struct pci_bus *card;
+       struct list_head *list;
 
-       if (from == NULL) {
-               from = isapnp_cards;
-       } else {
-               from = from->next;
-       }
-       for (card = from; card; card = card->next) {
+       list = isapnp_cards.next;
+       if (from)
+               list = from->node.next;
+
+       while (list != &isapnp_cards) {
+               struct pci_bus *card = list_entry(list, struct pci_bus, node);
                if (card->vendor == vendor && card->device == device)
                        return card;
+               list = list->next;
        }
        return NULL;
 }
@@ -1171,39 +1160,45 @@ struct pci_dev *isapnp_find_dev(struct pci_bus *card,
                                unsigned short function,
                                struct pci_dev *from)
 {
-       struct pci_dev *dev;
-       int idx;
-       
        if (card == NULL) {     /* look for a logical device from all cards */
-               if (from == NULL) {
-                       from = isapnp_devices;
-               } else {
-                       from = from->next;
-               }
-               for (dev = from; dev; dev = dev->next) {
+               struct list_head *list;
+
+               list = isapnp_devices.next;
+               if (from)
+                       list = from->global_list.next;
+
+               while (list != &isapnp_devices) {
+                       int idx;
+                       struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
+
                        if (dev->vendor == vendor && dev->device == function)
                                return dev;
                        for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
                                if (dev->vendor_compatible[idx] == vendor &&
                                    dev->device_compatible[idx] == function)
                                        return dev;
+                       list = list->next;
                }
        } else {
-               if (from == NULL) {
-                       from = card->devices;
-               } else {
-                       from = from->next;
-               }
+               struct list_head *list;
+
+               list = card->devices.next;
+               if (from)
+                       list = from->bus_list.next;
                if (from->bus != card)  /* something is wrong */
                        return NULL;
-               for (dev = from; dev; dev = dev->sibling) {
+               while (list != &card->devices) {
+                       int idx;
+                       struct pci_dev *dev = list_entry(list, struct pci_dev, bus_list);
+
                        if (dev->vendor == vendor && dev->device == function)
                                return dev;
                        for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
                                if (dev->vendor_compatible[idx] == vendor &&
                                    dev->device_compatible[idx] == function)
                                        return dev;
-               }               
+                       list = list->next;
+               }
        }
        return NULL;
 }
@@ -1442,7 +1437,7 @@ static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int
 {
        int i, tmp, rport, rsize;
        struct isapnp_port *xport;
-       struct pci_dev *dev;
+       struct list_head *list;
 
        if (check_region(port, size))
                return 1;
@@ -1454,7 +1449,9 @@ static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int
                if (port + size > rport && port + size < (rport + rsize) - 1)
                        return 1;
        }
-       for (dev = isapnp_devices; dev; dev = dev->next) {
+
+       for (list = isapnp_devices.next; list != &isapnp_devices ; list = list->next) {
+               struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
                if (dev->active) {
                        for (tmp = 0; tmp < 8; tmp++) {
                                if (dev->resource[tmp].flags) {
@@ -1543,7 +1540,7 @@ static void isapnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
 static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
 {
        int i;
-       struct pci_dev *dev;
+       struct list_head *list;
 
        if (irq < 0 || irq > 15)
                return 1;
@@ -1551,7 +1548,8 @@ static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
                if (isapnp_reserve_irq[i] == irq)
                        return 1;
        }
-       for (dev = isapnp_devices; dev; dev = dev->next) {
+       for (list = isapnp_devices.next; list != &isapnp_devices; list = list->next) {
+               struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
                if (dev->active) {
                        if (dev->irq_resource[0].start == irq ||
                            dev->irq_resource[1].start == irq)
@@ -1622,7 +1620,7 @@ static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx)
 static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
 {
        int i;
-       struct pci_dev *dev;
+       struct list_head *list;
 
        if (dma < 0 || dma == 4 || dma > 7)
                return 1;
@@ -1630,7 +1628,8 @@ static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
                if (isapnp_reserve_dma[i] == dma)
                        return 1;
        }
-       for (dev = isapnp_devices; dev; dev = dev->next) {
+       for (list = isapnp_devices.next; list != &isapnp_devices ; list = list->next) {
+               struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
                if (dev->active) {
                        if (dev->dma_resource[0].start == dma || dev->dma_resource[1].start == dma)
                                return 1;
@@ -1695,8 +1694,8 @@ static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsign
 {
        int i, tmp;
        unsigned int raddr, rsize;
-       struct pci_dev *dev;
        struct isapnp_mem *xmem;
+       struct list_head *list;
 
        for (i = 0; i < 8; i++) {
                raddr = (unsigned int)isapnp_reserve_mem[i << 1];
@@ -1708,7 +1707,8 @@ static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsign
                if (__check_region(&iomem_resource, addr, size))
                        return 1;
        }
-       for (dev = isapnp_devices; dev; dev = dev->next) {
+       for (list = isapnp_devices.next; list != &isapnp_devices ; list = list->next) {
+               struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
                if (dev->active) {
                        for (tmp = 0; tmp < 4; tmp++) {
                                if (dev->resource[tmp].flags) {
@@ -2052,23 +2052,14 @@ static int __init isapnp_do_reserve_irq(int irq)
 
 static void __init isapnp_pci_init(void)
 {
-       int devfn;
        struct pci_dev *dev;
-       
-       for (devfn = 0; devfn < 255; devfn++) {
-               dev = pci_find_slot(0, devfn);
-               if (dev != NULL)
-                       break;
-       }
-       if (dev == NULL)
-               return;
-       while (dev) {
+
+       pci_for_each_dev(dev) {
 #ifdef ISAPNP_DEBUG
                printk("PCI: reserved IRQ: %i\n", dev->irq);
 #endif
                if (dev->irq > 0)
                        isapnp_do_reserve_irq(dev->irq);
-               dev = dev->next;
        }
 }
 
@@ -2094,8 +2085,7 @@ EXPORT_SYMBOL(isapnp_resource_change);
 int __init isapnp_init(void)
 {
        int cards;
-       struct pci_bus *card;
-       struct pci_dev *dev;
+       struct list_head *list;
 
        if (isapnp_disable) {
                isapnp_detected = 0;
@@ -2144,15 +2134,20 @@ int __init isapnp_init(void)
        }
        isapnp_build_device_list();
        cards = 0;
-       for (card = isapnp_cards; card; card = card->next)
+
+       for (list = isapnp_cards.next; list != &isapnp_cards; list=list->next) {
+               struct pci_bus *card = list_entry(list, struct pci_bus, node);
+
                cards++;
-       if (isapnp_verbose) {
-               for (card = isapnp_cards; card; card = card->next) {
+               if (isapnp_verbose) {
+                       struct list_head *devlist;
                        printk( "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
                        if (isapnp_verbose < 2)
                                continue;
-                       for (dev = card->devices; dev; dev = dev->next)
+                       for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
+                               struct pci_dev *dev = list_entry(list, struct pci_dev, bus_list);
                                printk("isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
+                       }
                }
        }
        if (cards) {
index f78e3488bf4c82285c1f93285caf2908826aab97..0f0eb6a39a516a4419029ec906e418f5752c9485 100644 (file)
@@ -20,8 +20,6 @@
  */
 
 static void *isapnp_alloc(long size);
-struct pci_bus *isapnp_cards;
-struct pci_dev *isapnp_devices;
 
 struct isapnp_info_buffer {
        char *buffer;           /* pointer to begin of buffer */
@@ -539,10 +537,12 @@ static void isapnp_print_device(isapnp_info_buffer_t *buffer, struct pci_dev *de
  
 static void isapnp_info_read(isapnp_info_buffer_t *buffer)
 {
-       struct pci_bus *card;
-       struct pci_dev *dev;
+       struct list_head *card_list;
        
-       for (card = isapnp_cards; card; card = card->next) {
+       for (card_list = isapnp_cards.next; card_list != &isapnp_cards; card_list = card_list->next) {
+               struct pci_bus *card = list_entry(card_list, struct pci_bus, node);
+               struct list_head *dev_list;
+
                isapnp_printf(buffer, "Card %i '", card->number);
                isapnp_print_devid(buffer, card->vendor, card->device);
                isapnp_printf(buffer, ":%s'", card->name[0]?card->name:"Unknown");
@@ -551,8 +551,10 @@ static void isapnp_info_read(isapnp_info_buffer_t *buffer)
                if (card->productver)
                        isapnp_printf(buffer, " Product version %x.%x", card->productver >> 4, card->productver & 0x0f);
                isapnp_printf(buffer,"\n");
-               for (dev = card->devices; dev; dev = dev->sibling)
+               for (dev_list = card->devices.next; dev_list != &card->devices; dev_list = dev_list->next) {
+                       struct pci_dev *dev = list_entry(dev_list, struct pci_dev, bus_list);
                        isapnp_print_device(buffer, dev);
+               }
        }
 }
 
@@ -640,14 +642,17 @@ static int isapnp_set_card(char *line)
 static int isapnp_select_csn(char *line)
 {
        int csn;
+       struct list_head *list;
        char index[16], value[32];
 
        isapnp_info_device = NULL;
        isapnp_get_str(index, line, sizeof(index));
        csn = simple_strtoul(index, NULL, 0);
-       for (isapnp_info_card = isapnp_cards; isapnp_info_card; isapnp_info_card = isapnp_info_card->next)
+       for (list = isapnp_cards.next; list != &isapnp_cards; list = list->next) {
+               isapnp_info_card = list_entry(list, struct pci_bus, node);
                if (isapnp_info_card->number == csn)
                        break;
+       }
        if (isapnp_info_card == NULL) {
                printk("isapnp: cannot find CSN %i\n", csn);
                return 1;
index 95141ebd248f4f8be031e042886c84e1a6368238..7df2b9e5876a698d9b279d5768ca7aa991cfb9bc 100644 (file)
@@ -1411,37 +1411,27 @@ int findCard (Scsi_Host_Template * pHostTmpl,
 {
   mega_host_config *megaCfg;
   struct Scsi_Host *host;
-  u_char pciBus, pciDevFun, megaIrq;
+  u_char megaIrq;
   u32 megaBase;
-  u16 pciIdx = 0;
   u16 numFound = 0;
 
-  struct pci_dev *pdev = pci_devices;
+  struct pci_dev *pdev = NULL;
   
   while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
-    pciBus = pdev->bus->number;
-    pciDevFun = pdev->devfn;
     if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
       u16 magic;
-      pcibios_read_config_word (pciBus, pciDevFun,
-                               PCI_CONF_AMISIG,
-                               &magic);
-      if (magic != AMI_SIGNATURE) {
-        pciIdx++;
+      pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic);
+      if (magic != AMI_SIGNATURE)
        continue;               /* not an AMI board */
-      }
     }
-    printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:func %d\n",
+    printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x: in %s\n",
            pciVendor,
            pciDev,
-           pciIdx, pciBus,
-           PCI_SLOT (pciDevFun),
-           PCI_FUNC (pciDevFun));
+           pdev->slot_name);
 
     /* Read the base port and IRQ from PCI */
     megaBase = pdev->resource[0].start;
     megaIrq  = pdev->irq;
-    pciIdx++;
 
     if (flag & BOARD_QUARTZ) {
 
@@ -1470,7 +1460,7 @@ int findCard (Scsi_Host_Template * pHostTmpl,
     megaCfg->host->irq = megaIrq;
     megaCfg->host->io_port = megaBase;
     megaCfg->host->n_io_port = 16;
-    megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
+    megaCfg->host->unique_id = (pdev->bus->number << 8) | pdev->devfn;
     megaCtlrs[numCtlrs++] = megaCfg; 
     if (flag != BOARD_QUARTZ) {
       /* Request our IO Range */
index 560052291eaace7314dfab4200cc058360f53c1a..b378a1300362efce4cd5ed48dd4a12d1216c4d7f 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *      es1370.c  --  Ensoniq ES1370/Asahi Kasei AK4531 audio driver.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      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
  *  there are several MIDI to PCM (WAV) packages, one of them is timidity.
  *
  *  Revision history
- *    26.03.98   0.1   Initial release
- *    31.03.98   0.2   Fix bug in GETOSPACE
- *    04.04.98   0.3   Make it work (again) under 2.0.33
- *                     Fix mixer write operation not returning the actual
- *                     settings
- *    05.04.98   0.4   First attempt at using the new PCI stuff
- *    29.04.98   0.5   Fix hang when ^C is pressed on amp
- *    07.05.98   0.6   Don't double lock around stop_*() in *_release()
- *    10.05.98   0.7   First stab at a simple midi interface (no bells&whistles)
- *    14.05.98   0.8   Don't allow excessive interrupt rates
- *    08.06.98   0.9   First release using Alan Cox' soundcore instead of
- *                     miscdevice
- *    05.07.98   0.10  Fixed the driver to correctly maintin OSS style volume
- *                     settings (not sure if this should be standard)
- *                     Fixed many references: f_flags should be f_mode
- *                     -- Gerald Britton <gbritton@mit.edu>
- *    03.08.98   0.11  Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *                     Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se
- *                     On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
- *                     as it produces an annoying ssssh in the lower sampling rate
- *                     Do not include modversions.h
- *    22.08.98   0.12  Mixer registers actually have 5 instead of 4 bits
- *                     pointed out by Itai Nahshon
- *    31.08.98   0.13  Fix realplayer problems - dac.count issues
- *    08.10.98   0.14  Joystick support fixed
- *                    -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
- *    10.12.98   0.15  Fix drain_dac trying to wait on not yet initialized DMA
- *    16.12.98   0.16  Don't wake up app until there are fragsize bytes to read/write
- *    06.01.99   0.17  remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.18  cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *    22.03.99   0.19  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.20  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *                     Note: joystick address handling might still be wrong on archs
- *                     other than i386
- *    10.05.99   0.21  Added support for an electret mic for SB PCI64
- *                     to the Linux kernel sound driver. This mod also straighten
- *                     out the question marks around the mic impedance setting
- *                     (micz). From Kim.Berts@fisub.mail.abb.com
- *    11.05.99   0.22  Implemented the IMIX call to mute recording monitor.
- *                     Guenter Geiger <geiger@epy.co.at>
- *    15.06.99   0.23  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.24  Add pci_set_master
- *    02.08.99   0.25  Added workaround for the "phantom write" bug first
- *                     documented by Dave Sharpless from Anchor Games
- *    03.08.99   0.26  adapt to Linus' new __setup/__initcall
- *                     added kernel command line option "es1370=joystick[,lineout[,micbias]]"
- *                     removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
- *    12.08.99   0.27  module_init/__setup fixes
- *    19.08.99   0.28  SOUND_MIXER_IMIX fixes, reported by Gianluca <gialluca@mail.tiscalinet.it>
- *    31.08.99   0.29  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.30  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    28.10.99   0.31  More waitqueue races fixed
+ *    26.03.1998   0.1   Initial release
+ *    31.03.1998   0.2   Fix bug in GETOSPACE
+ *    04.04.1998   0.3   Make it work (again) under 2.0.33
+ *                       Fix mixer write operation not returning the actual
+ *                       settings
+ *    05.04.1998   0.4   First attempt at using the new PCI stuff
+ *    29.04.1998   0.5   Fix hang when ^C is pressed on amp
+ *    07.05.1998   0.6   Don't double lock around stop_*() in *_release()
+ *    10.05.1998   0.7   First stab at a simple midi interface (no bells&whistles)
+ *    14.05.1998   0.8   Don't allow excessive interrupt rates
+ *    08.06.1998   0.9   First release using Alan Cox' soundcore instead of
+ *                       miscdevice
+ *    05.07.1998   0.10  Fixed the driver to correctly maintin OSS style volume
+ *                       settings (not sure if this should be standard)
+ *                       Fixed many references: f_flags should be f_mode
+ *                       -- Gerald Britton <gbritton@mit.edu>
+ *    03.08.1998   0.11  Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *                       Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se
+ *                       On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
+ *                       as it produces an annoying ssssh in the lower sampling rate
+ *                       Do not include modversions.h
+ *    22.08.1998   0.12  Mixer registers actually have 5 instead of 4 bits
+ *                       pointed out by Itai Nahshon
+ *    31.08.1998   0.13  Fix realplayer problems - dac.count issues
+ *    08.10.1998   0.14  Joystick support fixed
+ *                      -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
+ *    10.12.1998   0.15  Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.1998   0.16  Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.1999   0.17  remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.18  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *    22.03.1999   0.19  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.20  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *                       Note: joystick address handling might still be wrong on archs
+ *                       other than i386
+ *    10.05.1999   0.21  Added support for an electret mic for SB PCI64
+ *                       to the Linux kernel sound driver. This mod also straighten
+ *                       out the question marks around the mic impedance setting
+ *                       (micz). From Kim.Berts@fisub.mail.abb.com
+ *    11.05.1999   0.22  Implemented the IMIX call to mute recording monitor.
+ *                       Guenter Geiger <geiger@epy.co.at>
+ *    15.06.1999   0.23  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.24  Add pci_set_master
+ *    02.08.1999   0.25  Added workaround for the "phantom write" bug first
+ *                       documented by Dave Sharpless from Anchor Games
+ *    03.08.1999   0.26  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line option "es1370=joystick[,lineout[,micbias]]"
+ *                       removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
+ *    12.08.1999   0.27  module_init/__setup fixes
+ *    19.08.1999   0.28  SOUND_MIXER_IMIX fixes, reported by Gianluca <gialluca@mail.tiscalinet.it>
+ *    31.08.1999   0.29  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.30  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    28.10.1999   0.31  More waitqueue races fixed
  *
  * some important things missing in Ensoniq documentation:
  *
index 66e6e0eb20e0a04c240c5e80d9fcc04ce59e7b41..0b3d33d8d4c3bceef699c29b728ed7240666784f 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *      es1371.c  --  Creative Ensoniq ES1371.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      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
  *  there are several MIDI to PCM (WAV) packages, one of them is timidity.
  *
  *  Revision history
- *    04.06.98   0.1   Initial release
- *                     Mixer stuff should be overhauled; especially optional AC97 mixer bits
- *                     should be detected. This results in strange behaviour of some mixer
- *                     settings, like master volume and mic.
- *    08.06.98   0.2   First release using Alan Cox' soundcore instead of miscdevice
- *    03.08.98   0.3   Do not include modversions.h
- *                     Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *    31.08.98   0.4   Fix realplayer problems - dac.count issues
- *    27.10.98   0.5   Fix joystick support
- *                     -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
- *    10.12.98   0.6   Fix drain_dac trying to wait on not yet initialized DMA
- *    23.12.98   0.7   Fix a few f_file & FMODE_ bugs
- *                     Don't wake up app until there are fragsize bytes to read/write
- *    06.01.99   0.8   remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.9   cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *    22.03.99   0.10  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.11  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *                     Another Alpha fix (wait_src_ready in init routine)
- *                     reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
- *                     Note: joystick address handling might still be wrong on archs
- *                     other than i386
- *    15.06.99   0.12  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.13  Add pci_set_master
- *    03.08.99   0.14  adapt to Linus' new __setup/__initcall
- *                     added kernel command line option "es1371=joystickaddr"
- *                     removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
- *    10.08.99   0.15  (Re)added S/PDIF module option for cards revision >= 4.
- *                     Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
- *                     module_init/__setup fixes
- *    08.16.99   0.16  Joe Cotellese <joec@ensoniq.com>
- *                     Added detection for ES1371 revision ID so that we can
- *                     detect the ES1373 and later parts.
- *                     added AC97 #defines for readability
- *                     added a /proc file system for dumping hardware state
- *                     updated SRC and CODEC w/r functions to accomodate bugs
- *                     in some versions of the ES137x chips.
- *    31.08.99   0.17  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.18  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    21.10.99   0.19  Round sampling rates, requested by
- *                     Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
- *    27.10.99   0.20  Added SigmaTel 3D enhancement string
- *                     Codec ID printing changes
- *    28.10.99   0.21  More waitqueue races fixed
- *                     Joe Cotellese <joec@ensoniq.com>
- *                     Changed PCI detection routine so we can more easily
- *                     detect ES137x chip and derivatives.
+ *    04.06.1998   0.1   Initial release
+ *                       Mixer stuff should be overhauled; especially optional AC97 mixer bits
+ *                       should be detected. This results in strange behaviour of some mixer
+ *                       settings, like master volume and mic.
+ *    08.06.1998   0.2   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.1998   0.3   Do not include modversions.h
+ *                       Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *    31.08.1998   0.4   Fix realplayer problems - dac.count issues
+ *    27.10.1998   0.5   Fix joystick support
+ *                       -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
+ *    10.12.1998   0.6   Fix drain_dac trying to wait on not yet initialized DMA
+ *    23.12.1998   0.7   Fix a few f_file & FMODE_ bugs
+ *                       Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.1999   0.8   remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.9   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *    22.03.1999   0.10  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.11  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *                       Another Alpha fix (wait_src_ready in init routine)
+ *                       reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
+ *                       Note: joystick address handling might still be wrong on archs
+ *                       other than i386
+ *    15.06.1999   0.12  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.13  Add pci_set_master
+ *    03.08.1999   0.14  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line option "es1371=joystickaddr"
+ *                       removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
+ *    10.08.1999   0.15  (Re)added S/PDIF module option for cards revision >= 4.
+ *                       Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
+ *                       module_init/__setup fixes
+ *    08.16.1999   0.16  Joe Cotellese <joec@ensoniq.com>
+ *                       Added detection for ES1371 revision ID so that we can
+ *                       detect the ES1373 and later parts.
+ *                       added AC97 #defines for readability
+ *                       added a /proc file system for dumping hardware state
+ *                       updated SRC and CODEC w/r functions to accomodate bugs
+ *                       in some versions of the ES137x chips.
+ *    31.08.1999   0.17  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.18  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    21.10.1999   0.19  Round sampling rates, requested by
+ *                       Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
+ *    27.10.1999   0.20  Added SigmaTel 3D enhancement string
+ *                       Codec ID printing changes
+ *    28.10.1999   0.21  More waitqueue races fixed
+ *                       Joe Cotellese <joec@ensoniq.com>
+ *                       Changed PCI detection routine so we can more easily
+ *                       detect ES137x chip and derivatives.
+ *    05.01.2000   0.22  Should now work with rev7 boards; patch by
+ *                       Eric Lemar, elemar@cs.washington.edu
  */
 
 /*****************************************************************************/
@@ -1260,7 +1262,7 @@ static int mixer_rdch(struct es1371_state *s, unsigned int ch, int *arg)
                
        case SOUND_MIXER_SPEAKER:
                j = rdcodec(s, AC97_PCBEEP_VOL);
-               if (j & AC97_MUTE
+               if (j & AC97_MUTE)
                        return put_user(0, (int *)arg);
                return put_user(0x6464 - ((j >> 1) & 0xf) * 0x606, (int *)arg);
                
@@ -3132,8 +3134,8 @@ static int __init probe_chip(struct pci_dev *pcidev, int index)
        pci_set_master(pcidev);  /* enable bus mastering */
        /* if we are a 5880 turn on the AC97 */
        if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
-           s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 &&
-           s->rev == CT5880REV_CT5880_C) {
+           ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev == CT5880REV_CT5880_C) || 
+            (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A))) { 
                cssr |= CSTAT_5880_AC97_RST;
                outl(cssr, s->io+ES1371_REG_STATUS);
                /* need to delay around 20ms(bleech) to give
index 769d9a1262d4d91c2b7459f5c46c3426c2b428f6..bf9d30bc66f66313c6df9acfd74fe05f1a90f6b6 100644 (file)
@@ -61,6 +61,8 @@
  *    07.10.99   0.9   Fix initialization; complain if sequencer writes time out
  *                     Revised resource grabbing for the FM synthesizer
  *    28.10.99   0.10  More waitqueue races fixed
+ *    09.12.99   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
+ *                     Disabling recording on Alpha
  *
  */
 
@@ -419,6 +421,14 @@ static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, int gfp_mask)
                                break;
                if (!db->rawbuf)
                        return -ENOMEM;
+               /* work around a problem of the alpha port */
+               if ((gfp_mask & GFP_DMA) && (virt_to_bus(db->rawbuf) & (~0xffffffUL))) {
+                       printk(KERN_ERR "solo1: requested DMA buffer below 16M but got 0x%lx, Alpha bug?\n", 
+                              (unsigned long)virt_to_bus(db->rawbuf));
+                       kfree(db->rawbuf);
+                       db->rawbuf = NULL;
+                       return -ENOMEM;
+               }
                db->buforder = order;
                /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
                mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
@@ -1417,6 +1427,12 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                if (s->dma_dac.mapped)
                        s->dma_dac.count &= s->dma_dac.fragsize-1;
                spin_unlock_irqrestore(&s->lock, flags);
+#if 0
+               printk(KERN_DEBUG "esssolo1: GETOPTR: bytes %u blocks %u ptr %u, buforder %u numfrag %u fragshift %u\n"
+                      KERN_DEBUG "esssolo1: swptr %u count %u fragsize %u dmasize %u fragsamples %u\n",
+                      cinfo.bytes, cinfo.blocks, cinfo.ptr, s->dma_dac.buforder, s->dma_dac.numfrag, s->dma_dac.fragshift,
+                      s->dma_dac.swptr, s->dma_dac.count, s->dma_dac.fragsize, s->dma_dac.dmasize, s->dma_dac.fragsamples);
+#endif
                 return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
 
         case SNDCTL_DSP_GETBLKSIZE:
@@ -1549,10 +1565,6 @@ static int solo1_open(struct inode *inode, struct file *file)
        s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
        up(&s->open_sem);
        MOD_INC_USE_COUNT;
-       if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) {
-               solo1_release(inode, file);
-               return -ENOMEM;
-       }
        prog_codec(s);
        return 0;
 }
@@ -2142,7 +2154,7 @@ static int __init init_solo1(void)
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "solo1: version v0.10 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n");
        while (index < NR_DEVICE && 
               (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
                if (!RSRCISIOREGION(pcidev, 0) ||
index a066c65b9674506c0711f0ec1aa1526450eea76c..4c817739d23b2b95cc1560f31394948ac13de7f2 100644 (file)
@@ -45,14 +45,7 @@ static void nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy);
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 
-/* eeeew. */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
-#else
-#define RSRCADDRESS(dev,num) ((dev)->base_address[(num)] \
-                             & PCI_BASE_ADDRESS_MEM_MASK)
-
-#endif
 
 /* List of cards.  */
 static struct nm256_info *nmcard_list;
index 20f9107983e02cf26c2d4fb84e5ff502e4902d40..41a0ef83a17a46b503b2b96a0916a78e2c49bf89 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *      sonicvibes.c  --  S3 Sonic Vibes audio driver.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      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
  *  out first how to drive them...
  *
  *  Revision history
- *    06.05.98   0.1   Initial release
- *    10.05.98   0.2   Fixed many bugs, esp. ADC rate calculation
- *                     First stab at a simple midi interface (no bells&whistles)
- *    13.05.98   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
- *                     set_dac_rate in the FMODE_WRITE case in sv_open
- *                     Fix hwptr out of bounds (now mpg123 works)
- *    14.05.98   0.4   Don't allow excessive interrupt rates
- *    08.06.98   0.5   First release using Alan Cox' soundcore instead of miscdevice
- *    03.08.98   0.6   Do not include modversions.h
- *                     Now mixer behaviour can basically be selected between
- *                     "OSS documented" and "OSS actual" behaviour
- *    31.08.98   0.7   Fix realplayer problems - dac.count issues
- *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA
- *    16.12.98   0.9   Fix a few f_file & FMODE_ bugs
- *    06.01.99   0.10  remove the silly SA_INTERRUPT flag.
- *                     hopefully killed the egcs section type conflict
- *    12.03.99   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *    22.03.99   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    05.04.99   0.13  added code to sv_read and sv_write which should detect
- *                     lockups of the sound chip and revive it. This is basically
- *                     an ugly hack, but at least applications using this driver
- *                     won't hang forever. I don't know why these lockups happen,
- *                     it might well be the motherboard chipset (an early 486 PCI
- *                     board with ALI chipset), since every busmastering 100MB
- *                     ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
- *                     exhibit similar behaviour (they work for a couple of packets
- *                     and then lock up and can be revived by ifconfig down/up).
- *    07.04.99   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *                     Note: dmaio hack might still be wrong on archs other than i386
- *    15.06.99   0.15  Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.16  Add pci_set_master
- *    03.08.99   0.17  adapt to Linus' new __setup/__initcall
- *                     added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
- *    12.08.99   0.18  module_init/__setup fixes
- *    24.08.99   0.19  get rid of the dmaio kludge, replace with allocate_resource
- *    31.08.99   0.20  add spin_lock_init
- *                     __initlocaldata to fix gcc 2.7.x problems
- *                     use new resource allocation to allocate DDMA IO space
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.21  change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    28.10.99   0.22  More waitqueue races fixed
- *    01.12.99   0.23  New argument to allocate_resource
- *    07.12.99   0.24  More allocate_resource semantics change
+ *    06.05.1998   0.1   Initial release
+ *    10.05.1998   0.2   Fixed many bugs, esp. ADC rate calculation
+ *                       First stab at a simple midi interface (no bells&whistles)
+ *    13.05.1998   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of
+ *                       set_dac_rate in the FMODE_WRITE case in sv_open
+ *                       Fix hwptr out of bounds (now mpg123 works)
+ *    14.05.1998   0.4   Don't allow excessive interrupt rates
+ *    08.06.1998   0.5   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.1998   0.6   Do not include modversions.h
+ *                       Now mixer behaviour can basically be selected between
+ *                       "OSS documented" and "OSS actual" behaviour
+ *    31.08.1998   0.7   Fix realplayer problems - dac.count issues
+ *    10.12.1998   0.8   Fix drain_dac trying to wait on not yet initialized DMA
+ *    16.12.1998   0.9   Fix a few f_file & FMODE_ bugs
+ *    06.01.1999   0.10  remove the silly SA_INTERRUPT flag.
+ *                       hopefully killed the egcs section type conflict
+ *    12.03.1999   0.11  cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *    22.03.1999   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    05.04.1999   0.13  added code to sv_read and sv_write which should detect
+ *                       lockups of the sound chip and revive it. This is basically
+ *                       an ugly hack, but at least applications using this driver
+ *                       won't hang forever. I don't know why these lockups happen,
+ *                       it might well be the motherboard chipset (an early 486 PCI
+ *                       board with ALI chipset), since every busmastering 100MB
+ *                       ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
+ *                       exhibit similar behaviour (they work for a couple of packets
+ *                       and then lock up and can be revived by ifconfig down/up).
+ *    07.04.1999   0.14  implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *                       Note: dmaio hack might still be wrong on archs other than i386
+ *    15.06.1999   0.15  Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.16  Add pci_set_master
+ *    03.08.1999   0.17  adapt to Linus' new __setup/__initcall
+ *                       added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
+ *    12.08.1999   0.18  module_init/__setup fixes
+ *    24.08.1999   0.19  get rid of the dmaio kludge, replace with allocate_resource
+ *    31.08.1999   0.20  add spin_lock_init
+ *                       __initlocaldata to fix gcc 2.7.x problems
+ *                       use new resource allocation to allocate DDMA IO space
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.21  change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    28.10.1999   0.22  More waitqueue races fixed
+ *    01.12.1999   0.23  New argument to allocate_resource
+ *    07.12.1999   0.24  More allocate_resource semantics change
  *
  */
 
diff --git a/drivers/usb/CREDITS b/drivers/usb/CREDITS
deleted file mode 100644 (file)
index 04e6760..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-Credits for the Simple Linux USB Driver:
-
-The following people have contributed to this code (in alphabetical
-order by last name).  I'm sure this list should be longer, its
-difficult to maintain, add yourself with a patch if desired.
-
-  Alan Cox <alan@lxorguk.ukuu.org.uk>
-  Johannes Erdfelt <jerdfelt@sventech.com>
-  ham <ham@unsuave.com>
-  Bradley M Keryan <keryan@andrew.cmu.edu>
-  Paul Mackerras <paulus@cs.anu.edu.au>
-  David E. Nelson <dnelson@jump.net>
-  Vojtech Pavlik <vojtech@suse.cz>
-  Gregory P. Smith <greg@electricrain.com>
-  Linus Torvalds <torvalds@transmeta.com>
-  Roman Weissgaerber <weissg@vienna.at>
-  <Kazuki.Yasumatsu@fujixerox.co.jp>
-
-Special thanks to:
-
-  Inaky Perez Gonzalez <inaky@peloncho.fis.ucm.es> for starting the
-  Linux USB driver effort and writing much of the larger uusbd driver.
-  Much has been learned from that effort.
-
-  The NetBSD & FreeBSD USB developers.  For being on the Linux USB list
-  and offering suggestions and sharing implementation experiences.
-
-Additional thanks to the following companies and people for donations
-of hardware, support, time and development (this is from the original
-THANKS file in Inaky's driver):
-
-        The following corporations have helped us in the development
-        of Linux USB / UUSBD:
-
-       - 3Com GmbH for donating a ISDN Pro TA and supporting me
-         in technical questions and with test equipment. I'd never 
-         expect such a great help.
-
-        - USAR Systems provided us with one of their excellent USB
-          Evaluation Kits. It allows us to test the Linux-USB driver
-          for compilance with the latest USB specification. USAR
-          Systems recognized the importance of an up-to-date open
-          Operating System and supports this project with
-          Hardware. Thanks!.
-
-        - Thanks to Intel Corporation for their precious help.
-
-        - We teamed up with Cherry to make Linux the first OS with
-          built-in USB support. Cherry is one of the biggest keyboard
-          makers in the world.
-
-        - CMD Technology, Inc. sponsored us kindly donating a CSA-6700
-          PCI-to-USB Controller Board to test the OHCI implementation.
-
-        - Due to their support to us, Keytronic can be sure that they
-          will sell keyboards to some of the 3 million (at least)
-          Linux users.
-
-        - Many thanks to ing büro h doran [http://www.ibhdoran.com]!
-          It was almost imposible to get a PC backplate USB connector
-          for the motherboard here at Europe (mine, home-made, was
-          quite lowsy :). Now I know where to adquire nice USB stuff!
-
-        - Genius Germany donated a USB mouse to test the mouse boot
-          protocol. They've also donated a F-23 digital joystick and a
-          NetMouse Pro. Thanks! 
-
-        - AVM GmbH Berlin is supporting the development of the Linux
-          USB driver for the AVM ISDN Controller B1 USB. AVM is a
-          leading manufacturer for active and passive ISDN Controllers
-          and CAPI 2.0-based software. The active design of the AVM B1
-          is open for all OS platforms, including Linux.
-
-        - Thanks to Y-E Data, Inc. for donating their FlashBuster-U
-          USB Floppy Disk Drive, so we could test the bulk transfer
-          code.
-
-        - Many thanks to Logitech for contributing a three axis USB
-          mouse. 
-
-          Logitech designs, manufactures and markets
-          Human Interface Devices, having a long history and
-          experience in making devices such as keyboards, mice,
-          trackballs, cameras, loudspeakers and control devices for
-          gaming and professional use.
-
-          Being a recognized vendor and seller for all these devices,
-          they have donated USB mice, a joystick and a scanner, as a
-          way to acknowledge the importance of Linux and to allow
-          Logitech customers to enjoy support in their favorite
-          operating systems and all Linux users to use Logitech and
-          other USB hardware.
-
-          Logitech is official sponsor of the Linux Conference on
-          Feb. 11th 1999 in Vienna, where we'll will present the
-          current state of the Linux USB effort.
-
-        - CATC has provided means to uncover dark corners of the UHCI
-          inner workings with a USB Inspector.
-
-        - Thanks to Entrega for providing PCI to USB cards, hubs and
-          converter products for development. 
-
-
-        And thanks go to (hey! in no particular order :)
-
-        - Oren Tirosh <orenti@hishome.net>, for standing so patiently
-          all my doubts'bout USB and giving lots of cool ideas.
-
-        - Jochen Karrer <karrer@wpfd25.physik.uni-wuerzburg.de>, for
-          pointing out mortal bugs and giving advice.
-
-        - Edmund Humemberger <ed@atnet.at>, for it's great work on
-          public relationships and general management stuff for the
-          Linux-USB effort.
-
-        - Alberto Menegazzi <flash@flash.iol.it> is starting the
-          documentation for the UUSBD. Go for it!
-
-        - Ric Klaren <ia_ric@cs.utwente.nl> for doing nice
-          introductory documents (compiting with Alberto's :).
-
-        - Christian Groessler <cpg@aladdin.de>, for it's help on those
-          itchy bits ... :)
-
-        - Paul MacKerras for polishing OHCI and pushing me harder for
-          the iMac support, giving improvements and enhancements.
-
-        - Fernando Herrera <fherrera@eurielec.etsit.upm.es> has taken
-          charge of composing, maintaining and feeding the
-          long-awaited, unique and marvelous UUSBD FAQ! Tadaaaa!!!
-
-        - Rasca Gmelch <thron@gmx.de> has revived the raw driver and
-          pointed bugs, as well as started the uusbd-utils package.
-
-        - Peter Dettori <dettori@ozy.dec.com> is unconvering bugs like
-          crazy, as well as making cool suggestions, great :)
-
-        - All the Free Software and Linux community, the FSF & the GNU
-          project, the MIT X consortium, the TeX people ... everyone!
-          You know who you are!
-
-        - Big thanks to Richard Stallman for creating Emacs!
-
-        - The people at the linux-usb mailing list, for reading so
-          many messages :) Ok, no more kidding; for all your advices!
-
-        - All the people at the USB Implementors Forum for their
-          help and assistance.
-
-        - Nathan Myers <ncm@cantrip.org>, for his advice! (hope you
-          liked Cibeles' party).
-
-        - Linus Torvalds, for starting, developing and managing Linux.
-
-        - Mike Smith, Craig Keithley, Thierry Giron and Janet Schank
-          for convincing me USB Standard hubs are not that standard
-          and that's good to allow for vendor specific quirks on the
-          standard hub driver.
-
diff --git a/drivers/usb/README.URB b/drivers/usb/README.URB
deleted file mode 100644 (file)
index 67cb9e3..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-1. Specification of the API
-
-1.1. Basic concept or 'What is an URB?'
-
-The basic idea of the new driver is message passing, the message itself is 
-called USB Request Block, or URB for short. 
-
-- An URB consists of all relevant information to execute any USB transaction 
-and deliver the data and status back. 
-
-- Execution of an URB is an inherently asynchronous operation, i.e. the 
-submit_urb(urb) call returns immediately after it has successfully queued 
-the requested action. 
-
-- Ongoing transfers for one URB (e.g. ISO) can simply be canceled with
-unlink_urb(urb) at any time. 
-
-- Each URB has a completion handler, which is called after the action
-has been successfully completed or canceled (INT transfers behave a bit
-different, see below). The URB also contains a context-pointer for free 
-usage and information passing to the completion handler.
-
-- URBs can be linked. After completing one URB, the next one can be
-automatically submitted. This is especially useful for ISO transfers:
-You only have read/write the data from/to the buffers in the completion 
-handler, the continous streaming itself is transparently done by the 
-URB-machinery.
-
-1.2. The URB structure
-
-typedef struct urb
-{
-// ignore, for host controller/URB machine internal use
-       void *hcpriv;                   // private data for host controller
-       struct list_head urb_list;      // list pointer to all active urbs 
-
-// This is used for urb linking
-       struct urb* next;               // pointer to next URB  
-       struct usb_device *dev;         // pointer to associated USB device
-
-// pipe is assembled by the various well known pipe-macros in usb.h
-       unsigned int pipe;              // pipe information
-
-// status after each completion
-       int status;                     // returned status
-       unsigned int transfer_flags;    // ASAP, SP_OK, EARLY_COMPLETE
-
-// for data stage (CTRL), BULK, INT and ISO
-       void *transfer_buffer;          // associated data buffer
-
-// expected length
-       int transfer_buffer_length;     // data buffer length
-       int actual_length;              // actual data buffer length    
-
-// setup stage for CTRL (always 8 bytes!)
-       unsigned char* setup_packet;    // setup packet (control only)
-       
-// with ASAP, start_frame is set to the determined frame
-       int start_frame;                // start frame (iso/irq)
-       int number_of_packets;          // # of packets (iso/int)
-       int interval;                   // polling interval (irq only)
-       int error_count;                // number of errors (iso only)
-       //
-       void *context;                  // context for completion routine
-       usb_complete_t complete;        // pointer to completion routine
-       //
-// specification of the requested data offsets and length for ISO
-       iso_packet_descriptor_t  iso_frame_desc[0];
-} urb_t, *purb_t;
-
-1.3. How to get an URB?
-
-URBs are allocated with the following call
-
-       purb_t alloc_urb(int isoframes)
-
-Return value is a pointer to the allocated URB, 0 if allocation failed.
-The parameter isoframes specifies the number of isochronous transfer frames
-you want to schedule. For CTRL/BULK/INT, use 0.
-
-To free an URB, use
-
-       void free_urb(purb_t purb)
-
-This call also may free internal (host controller specific) memory in the
-future.
-
-1.4. What has to be filled in?
-
-Depending on the type of transaction, there are some macros 
-(FILL_CONTROL_URB, FILL_BULK_URB, and FILL_INT_URB, defined in uhci.h)
-that simplify the URB creation. In general, all macros need the usb
-device pointer, the pipe (usual format), the transfer buffer, the 
-desired transfer length, the completion  handler, and its context. 
-Take a look at the uhci_control_msg-function that convert the old API 
-into an URB.
-
-Flags:
-For ISO there are two startup behaviors: Specified start_frame or ASAP.
-For ASAP set USB_ISO_ASAP in transfer_flags.
-
-If short packets should NOT be tolerated, set USB_DISABLE_SPD in 
-transfer_flags.
-
-Usually, (to reduce restart time) the completion handler is called
-AFTER the URB re-submission. You can get the other way by setting
-USB_URB_EARLY_COMPLETE in transfer_flags. This is implicite for
-INT transfers.
-
-1.5. How to submit an URB?
-
-Just call
-
-       int submit_urb(purb_t purb)
-
-It immediately returns, either with status 0 (request queued) or some
-error code, usually caused by the following:
-
-- Out of memory (-ENOMEM)
-- Wrong pipe handle (-ENXIO)
-- Unplugged device (-ENODEV)
-- Stalled endpoint (-EPIPE)
-- Too many queued ISO transfers (-EAGAIN)
-- Too many requested ISO frames (-EFBIG)
-- Invalid INT interval (-EINVAL)
-- More than one packet for INT (-EINVAL)
-
-After submission, urb->status is USB_ST_URB_PENDING.
-
-For isochronous endpoints, subsequent submitting of URBs to the same endpoint
-with the ASAP flag result in a seamless ISO streaming. Exception: The 
-execution cannot be scheduled later than 900 frames from the 'now'-time. 
-The same applies to INT transfers, but here the seamless continuation is 
-independent of the transfer flags (implicitely ASAP).
-
-1.6. How to cancel an already running URB?
-
-Call
-       int unlink_urb(purb_t purb)
-
-It removes the urb from the internal list and frees all allocated
-HW descriptors. The status is changed to USB_ST_URB_KILLED. After 
-unlink_urb() returns, you can safely free the URB with free_urb(urb)
-and all other possibly associated data (urb->context etc.)
-
-1.7. What about the completion handler?
-
-The completion handler is optional, but useful for fast data processing
-or wakeup of a sleeping process (as shown in the compatibility wrapper's 
-completion handler).
-
-The handler is of the following type:
-
-       typedef void (*usb_complete_t)(struct urb *);
-
-i.e. it gets just the URB that caused the completion call.
-In the completion handler, you should have a look at urb->status to
-detect any USB errors. Since the context parameter is included in the URB,
-you can pass information to the completion handler. 
-
-
-1.8. How to do isochronous (ISO) transfers?
-
-For ISO transfers you have to append the iso_packet_descriptor_t structure 
-to the URB for each frame you want to schedule. When using alloc_urb(n)
-(recommended), the isoframe-parameter n can be used to allocate the
-structures for n frames.
-
-For each entry you have to specify the data offset for this frame (base is
-transfer_buffer), and the length you want to write/expect to read.
-After completion, actual_length contains the actual transfered length and 
-status contains the resulting USB-status for the ISO transfer for this frame.
-It is allowed to specify a varying length from frame to frame (e.g. for
-audio synchronisation/adaptive transfer rates). You can also use the length 
-0 to omit one or more frames (striping).
-
-As can be concluded from above, the UHCI-driver does not care for continous
-data in case of short packet ISO reads! There's no fixup_isoc() like in the 
-old driver. There may be a common routine to do this in the future, but this 
-has nothing to do with the UHCI-driver!
-
-For scheduling you can choose your own start frame or ASAP. As written above,
-queuing more than one ISO frame with ASAP to the same device&endpoint result 
-in seamless ISO streaming. For continous streaming you have to use URB
-linking. 
-
-1.9. How to start interrupt (INT) transfers?
-
-INT transfers are currently implemented with 8 different queues for intervals 
-for 1, 2, 4,... 128ms. Only one TD is allocated for each interrupt. After
-calling the completion handler, the TD is recycled.
-With the submission of one URB, the interrupt is scheduled until it is
-canceled by unlink_urb.
-
-The submit_urb()-call modifies urb->interval to the rounded value.
-
diff --git a/drivers/usb/README.acm b/drivers/usb/README.acm
deleted file mode 100644 (file)
index c978974..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-The ACM driver works with modems and ISDN TAs that use the USB Abstract
-Control Model standard. 
-
-****************************
-Test it:
-Watch out, the driver is not stable and tested. Sync often, make backups,
-most importand: don't blame me...
-
-Create device files:
-mknod /dev/ttyACM0 c 166 0
-mknod /dev/ttyACM1 c 166 1
-mknod /dev/ttyACM2 c 166 2
-mknod /dev/ttyACM3 c 166 3
-Compile a kernel with support for your host controller (uhci only for now!)
-and support for ACM. Boot this kernel. If you connect your device to the
-USB bus you should see messages like the following:
-
-Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
-Jul 19 20:14:29 office kernel: Found 02:09
-Jul 19 20:14:29 office kernel: Found 04:09
-Jul 19 20:14:29 office kernel: Found 05:07
-Jul 19 20:14:29 office last message repeated 2 times
-Jul 19 20:14:29 office kernel: parsed = 39 len = 67
-Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping
-Jul 19 20:14:29 office kernel:    0 09
-Jul 19 20:14:29 office kernel:    1 02
-Jul 19 20:14:29 office kernel:    2 43
-Jul 19 20:14:29 office kernel:    3 00
-Jul 19 20:14:29 office kernel:    4 02
-Jul 19 20:14:29 office kernel:    5 02
-Jul 19 20:14:29 office kernel:    6 04
-Jul 19 20:14:29 office kernel:    7 60
-Jul 19 20:14:29 office kernel:    8 00
-Jul 19 20:14:29 office kernel: Found 04:09
-Jul 19 20:14:29 office kernel: Found 02:09
-Jul 19 20:14:29 office kernel: Found 04:09
-Jul 19 20:14:29 office kernel: Found 05:07
-Jul 19 20:14:29 office kernel: Found 04:09
-Jul 19 20:14:29 office kernel: Found 05:07
-Jul 19 20:14:29 office kernel: Found 05:07
-Jul 19 20:14:29 office kernel: parsed = 67 len = 0
-Jul 19 20:14:29 office kernel: getstringtable
-Jul 19 20:14:29 office kernel: acm_probe
-Jul 19 20:14:29 office kernel: USB ACM found
-
-Watch out for the line:
-Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
-and the line:
-Jul 19 20:14:29 office kernel: USB ACM found
-These two lines show that the device was seen by the usb host controller and
-then recognized by the acm driver as a valid device.
-
-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 
-been able to do zmodem downloads to another pc. However downloads from one
-ISDN TA to another ISDN TA connected to the same PC didn't work. Don't
-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
-not finised with this. There might be a chance to get it working. However
-i'd like to know if your device is recognized as an ACM device. I'm also
-interested if the thing is stable or if it crashes.
-(should i say how it crases?)
-
-You should be able to add and remove devices from the bus. The driver will
-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 see but it's ok for now. (I hope ;-)
-
-Please report your experiences to me:
-fuerst@in.tum.de
-
-***************************
-I've tested it with:
-3Com ISDN Pro TA.
-
-It should work with (That means i know these devices conform to ACM):
-3Com Office Connect Modem
-3Com Sportster USB (I think that's what it's called)
-
-***************************
-Many thanks to 3Com which did not only support me with hardware but also
-with technical support in USB questions. They also allowed me to do tests in
-their lab. Great!
-
-***************************
-Known bugs:
-Flow control not tested (likely not to work)
-Some tty function calls not implemented (putchar, etc...)
-Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 )
-Not all mem is freed at close (need terminate irq in hcd)
-
-***************************
-Have fun,
-       Armin Fuerst
diff --git a/drivers/usb/README.dc2xx b/drivers/usb/README.dc2xx
deleted file mode 100644 (file)
index 25b0241..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-13 November 1999
-david-b@pacbell.net
-
-This is an overview of how to use the "dc2xx" USB driver with certain
-digital still cameras from Kodak and other vendors.
-
-
-CAMERAS
-
-This driver will mostly be used with Kodak DC-2xx series digital still
-cameras, but it should be trivial to tell it about several non-Kodak
-USB-enabled cameras.
-
-You'll most likely want to hook it up to recent versions of "gPhoto"
-(www.gphoto.org), since version 0.4 and later know how to use it to talk
-to Kodak DC-240 and DC-280 cameras over USB.
-
-In addition the DC-260, DC-265, and DC-290 are currently recognized.
-However, like other cameras using the "Digita OS" (from www.flashpoint.com)
-there is no gPhoto support for this camera.  At this writing the best
-known support for these cameras is a Python script that supports image
-downloading from those cameras.  (See archives of the linux-usb mailing
-list.)  The DC-220 should also work with this driver, given information
-about the USB product IDs.  When it becomes available, the HP PhotoSmart
-C500 should also work ... it's another Digita OS camera with USB support.)
-
-It's likely that other digital still cameras can also use this USB driver,
-even if they're not from Kodak and don't use Digita.  The reason is that
-most currently known USB still camera protocols treat USB like a faster
-packet-carrying connection than a serial line, which is exactly how this
-driver looks to an application.
-
-
-USB HARDWARE
-
-This has been shown to work on x86 OHCI and UHCI (Intel) chipsets.  OHCI has
-been trouble free; not so with UHCI, which was first seen to be happy with
-2.3.24 kernels, and has not been as fast as OHCI.
-
-Note that in some cases changes in BIOS settings may be needed before
-your USB works.  At least one user has reported a need for SMP-related 
-settings as well.
-
-As yet, no reports have come from Linux users on non-Intel hardware.
-(You could color coordinate your iMac with a DC-240i ... :-)
-
-
-SETUP
-
-Configure in the DC2XX USB driver, and have it in your kernel.  Recently I
-compile it right in, but I've done it as a module in the past.
-
-Create a device, perhaps like this (both read and write):
-
-    # mknod -m 0666 /dev/kodak c 10 170
-
-That "170" is not formally assigned, and this command may change.  If you're
-using a non-Kodak camera, you may prefer another name.
-
-Don't plug in more than one compatible camera at this time.  One of them
-will be ignored, but I'd not be sure which one!
-
-
-SANITY TESTING
-
-First:  if you've got /proc support, make sure that the driver has hooked
-itself up correctly.
-
-    - you should see an entry in /proc/misc for the a Kodak DC-2xx
-      minor device number
-
-    - you should see an entry in /proc/bus/usb/drivers for "dc2xx",
-      if you also enabled USB /proc support.
-
-Second:  when you connect your camera to the computer, does it get recognized
-by the driver?
-
-    - if you've got /proc/bus/usb/devices, you should see an entry
-      something like this.  The "ProdID" may be different if you didn't
-      plug in a DC-240, but the "Driver=dc2xx" had better be there.
-
-       T:  Lev=01 Prnt=00 Port=00 Cnt=01 Dev#=  1 Spd=12  MxCh= 0
-       D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
-       P:  Vendor=040a ProdID=0120 Rev= 1.08
-       C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=100mA
-       I:  If#= 0 Alt= 0 #EPs= 2 Cls=00(>ifc ) Sub=00 Prot=00 Driver=dc2xx
-       E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
-       E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
-
-    - if you don't have /proc support for USB, see if "dmesg" output
-      tells you that you plugged in your camera.
-
-       USB new device connect, assigned device number 1
-       Manufacturer: Eastman Kodak Company
-       Product: KODAK DC240 Zoom Digital Camera
-       USB Camera is connected
-       usbcore: dc2xx driver claimed interface c3a68600
-       ohci-control thread sleeping
-
-Third:  (optional) can you use gPhoto to talk to the camera?
-
-    - When you configure your camera, tell it to use "/dev/kodak" (or
-      whatever name you used).  Right now, gPhoto emits a diagnostic
-      message (non-GUI) saying that it since it didn't act like a TTY,
-      it's assuming it's got a USB connection.
-
-    - With the camera turned on, get the "camera summary".  It'll
-      talk to the camera -- and tell you you're using USB.
-
-If you got that far, you should be able to use everything fine.
diff --git a/drivers/usb/README.error-codes b/drivers/usb/README.error-codes
deleted file mode 100644 (file)
index 8366613..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-$Id: README.error-codes,v 1.1 1999/12/14 14:03:02 fliegl Exp $
-
-This is the documentation of (hopefully) all possible error codes (and
-their interpretation) that can be returned from the hostcontroller driver 
-and from usbcore.
-
-NOTE:
-The USB_ST_* codes are deferred and are only listed for compatibility, new
-software should use only -E* instead!
-
-
-
-**************************************************************************
-*                   Error codes returned by usb_submit_urb               *
-**************************************************************************
-
-Non-USB-specific:
-
-USB_ST_NOERROR
-0              URB submission went fine
-
--ENOMEM                no memory for allocation of internal structures 
-
-USB-specific:
-
--ENODEV                specified USB-device or bus doesn't exist
-
--ENXIO         specified endpoint doesn't exist on the device
-
-USB_ST_URB_INVALID_ERROR
--EINVAL                a) Invalid transfer type specified (or not supported)
-               b) Invalid interrupt interval (0<=n<256)
-               c) more than one interrupt packet requested
-
--EAGAIN                a) specified ISO start frame too early
-               b) (using ISO-ASAP) too much scheduled for the future
-                  wait some time and try again.
-
--EFBIG         too much ISO frames requested (currently uhci>900)
-
--EPIPE         specified pipe-handle is already stalled
-
--EMSGSIZE      endpoint message size is zero, do interface/alternate setting
-
-
-**************************************************************************
-*                   Error codes returned by in urb->status               *
-*                   or in iso_frame_desc[n].status (for ISO)             *
-**************************************************************************
-
-USB_ST_NOERROR
-0                      Transfer completed successfully
-
-USB_ST_URB_KILLED
--ENOENT                        URB was canceled by unlink_urb
-
-USB_ST_URB_PENDING
--EINPROGRESS           URB still pending, no results yet
-                       (actually no error until now;-)
-
-USB_ST_BITSTUFF
-USB_ST_INTERNALERROR
--EPROTO                        a) bitstuff error
-                       b) unknown USB error 
-
-USB_ST_CRC
--EILSEQ                        CRC mismatch
-
--EPIPE                 a) babble detect
-                       b) endpoint stalled
-
-USB_ST_BUFFERUNDERRUN
--ENOST                 buffer error
-
-USB_ST_NORESPONSE
-USB_ST_TIMEOUT
--ETIMEDOUT             transfer timed out, NAK
-
-USB_ST_REMOVED 
--ENODEV                        device was removed
-
-USB_ST_SHORT_PACKET
--EREMOTEIO             short packet detected
-
-USB_ST_PARTIAL_ERROR
--EXDEV                 ISO transfer only partially completed
-                       look at individual frame status for details
-
-USB_ST_URB_INVALID_ERROR
--EINVAL                        ISO madness, if this happens: Log off and go home
-
-**************************************************************************
-*              Error codes returned by usbcore-functions                 *
-*           (expect also other submit and transfer status codes)         *
-**************************************************************************
-
-usb_register():
-USB_ST_NOTSUPPORTED
--EINVAL                        error during registering new driver
-
-usb_terminate_bulk():
-USB_ST_REMOVED
--ENODEV                        urb already removed
-
-usb_get_*/usb_set_*():
-                       All USB errors (submit/status) can occur
-
-
diff --git a/drivers/usb/README.hid b/drivers/usb/README.hid
deleted file mode 100644 (file)
index 3cd3373..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-                          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.
diff --git a/drivers/usb/README.ohci_hcd b/drivers/usb/README.ohci_hcd
deleted file mode 100644 (file)
index 37a6372..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-
-The OHCI HCD layer is a simple but nearly complete implementation of what the
-USB people would call a HCD  for the OHCI. 
- (ISO comming soon, Bulk, INT u. CTRL transfers enabled)
-It is based on Linus Torvalds UHCI code and Gregory Smith OHCI fragments (0.03 source tree).
-The layer (functions) on top of it, is for interfacing to the alternate-usb device-drivers. 
-
-- Roman Weissgaerber <weissg@vienna.at>
-
- * v4.0 1999/08/18 removed all dummy eds, unlink unused eds, code cleanup, bulk transfers 
- * v2.1 1999/05/09 ep_addr correction, code cleanup
- * v0.2.0 1999/05/04 
- * everything has been moved into 2 files (ohci-hcd.c, ohci-hub-root.c and headers)
- * virtual root hub is now an option, 
- * memory allocation based on kmalloc and kfree now, simple Bus error handling, 
- * INT and CTRL transfers enabled, Bulk included but disabled, ISO needs completion
- * 
- * from Linus Torvalds (uhci.c): APM (not tested); hub, usb_device, bus and related stuff
- * from Greg Smith (ohci.c): better reset ohci-controller handling, hub
- * 
- * v0.1.0 1999/04/27 initial release
-to remove the module try:
-rmmod usb-ohci-hcd
-
-Features:
-- virtual root hub, all basic hub descriptors and commands (state: complete) 
-  this is an option now (v0.2.0)
-  #define  CONFIG_USB_OHCI_VROOTHUB includes the virtual hub code, (VROOTHUB)
-  default is with. 
-  (at the moment: the Virtual Root Hub is included automatically)
-  
-  files: ohci-root-hub.c, ohci-root-hub.h 
-
-- Endpoint Descriptor (ED) handling more static approach 
- (EDs should be allocated in parallel to the SET CONFIGURATION command and they live
- as long as the function (device) is alive or another configuration is choosen.
- In the HCD layer the EDs has to be allocated manually either by calling a subroutine
- or by sending a USB root hub vendor specific command to the virtual root hub.
- At the alternate linux usb stack EDs will be added (allocated) at their first use.
- ED will be unlinked from the HC chains if they are not bussy.
- files: ohci-hcd.c ohci-hcd.h
- routines:   (do not use for drivers, use the top layer alternate usb commands instead)
- int usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr1, 
-            int interval, int load, f_handler handler, int ep_size, int speed)
-       adds an endpoint, (if the endpoint already exists some parameters will be updated)
-       
- int usb_ohci_rm_ep( ) 
-       removes an endpoint and all pending TDs of that EP
-       
-  usb_ohci_rm_function( )
-       removes all Endpoints of a function (device)
-
-- Transfer Descriptors (TD): handling and allocation of TDs is transparent to the upper layers
-  The HCD takes care of TDs and EDs memory allocation whereas the upper layers (UBSD ...) has
-  to take care of buffer allocation.
-  files: ohci-hcd.c ohci-hcd.h 
-
-  There is one basic command for all types of bus transfers (INT, BULK, ISO, CTRL):
-  
-  int ohci_trans_req(struct ohci * ohci, hcd_ed, int ctrl_len, void  *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1)
-  
-  CTRL: ctrl, ctrl_len ... cmd buffer 
-        data, data_len ... data buffer (in or out)
-  INT, BULK:  ctrl = NULL, ctrl_len=0,
-               data, data_len ... data buffer (in or out)
-  ISO: tbd
-
-  There is no buffer reinsertion done by the internal HCD function. 
-  (The interface layer does this for a INT-pipe on request.)
-  If you want a transfer then you have to 
-  provide buffers by sending ohci_trans_req requests. As they are queued as TDs on an ED
-  you can send as many as you like. They should come back by the callback f_handler in
-  the same order (for each endpoint, not globally) If an error occurs all
-  queued transfers of an endpoint will return unsent. They will be marked with an error status.
-  
-  e.g double-buffering for int transfers:
-
-       ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0)
-       ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0)
-       
-  and when a data0 packet returns by the callback f_handler requeue it:
-       ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0)
-  and when a data1 packet returns by the callback f_handler requeue it:
-       ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0)
-       
-  lw0, lw1 are private fields for upper layers for ids or fine grained handlers.
-  The alternate usb uses them for dev_id and usb_device_irq handler.
-
-
-- Done list handling: returns the requests (callback f_handler in ED) and does 
-  some error handling, root-hub request dequeuing
-  (files: ohci-done-list.c in ohci-hcd.c now(v0.2.0))
-
-  
diff --git a/drivers/usb/README.ov511 b/drivers/usb/README.ov511
deleted file mode 100644 (file)
index 14163ae..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
--------------------------------------------------------------------------------
-Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
--------------------------------------------------------------------------------
-
-INTRODUCTION:
-
-This is a preliminary version of my OV511 Linux device driver. At the moment,
-it does not do much more than detect the chip and initialize it. As trivial
-as this sounds, it represents many hours of my work. Since OmniVision refused
-to release the full specs to me, I had to write code to probe out the register
-read/write commands. Some code is in place to allow a frame to be grabbed, but
-it is nowhere near complete.
-
-SUPPORTED CAMERAS:
-____________________________________________
-Manufacturer     | Model        | Custom ID 
------------------+--------------+-----------
-D-Link           | DSB-C300        | 3
-Creative Labs    | WebCam 3     | 21
---------------------------------------------
-
-Any camera using the OV511 and the OV7610 CCD should work with this driver. The
-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
-in the kernel logs. If you have an unsupported camera, please send me the model,
-manufacturer and ID number and I will add it to the detection code. In the
-meantime, you can add to the code yourself in the function ov511_probe()
-
-WHAT YOU NEED:
-
-- If you want to help with the development, get the chip's specification docs at
-  http://www.ovt.com/omniusbp.html
-
-- A Video4Linux compatible frame grabber program (I recommend vidcat)
-  (see: http://www.exploits.org/v4l/ )
-  
-WHAT NEEDS TO BE DONE:
-
-In short, a lot. 
-
-UPDATE:
-Currently, the control messages are working fine ("vendor commands"; for
-reading and writing the OV511 registers.) The I2C bus commands for reading and
-writing the camera (OV7610) registers are implemented and working, with at least
-one person's camera. The isochronous-in endpoint for video data is finally
-producing data, but since ov511_parse_data() is not implemented you will not see
-a picture yet.
-
-Support for specific CCD's will have to be implemented as well (such as the
-OV7610.) 
-
-The rest of the work will involve implementing support for all the different
-resolutions, color depths, etc. Also, while support for the OV511's proprietary
-lossy compression is apparently not necessary (the code currently disables it,)
-it would be a nice addition as it improves performance quite a bit. OmniVision
-wouldn't tell me how the algorithm works, so we can't really work on that yet.
-Please kindly inform OmniVision that you would like them to release their
-specifications to the Linux community.
-
-HOW TO CONTACT ME:
-
-You can email me at mmcclelland@delphi.com . Please prefix the subject line
-with "OV511: " so that I am certain to notice your message.
-
-CREDITS:
-
-The code is based in no small part on the CPiA driver by Johannes Erdfelt,
-Randy Dunlap, and others. Big thanks to them for their pioneering work on that
-and the USB stack. Thanks to Bret Wallach for getting camera reg IO and ISOC
-working.
diff --git a/drivers/usb/README.scanner b/drivers/usb/README.scanner
deleted file mode 100644 (file)
index 4b5de2b..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-Oct 19, 1999
-
-CHANGES
-
-- Ammended for linux-2.3.22+
-- Appended hp_scan.c to end of this README
-- Removed most references to HP
-
-
-OVERVIEW
-
-This README will address issues regarding how to configure the kernel
-to access a USB scanner.  Although the driver was originally conceived
-for USB HP scanners, it's general enough so that it can be used with
-other scanners.  Also, one can now pass the USB Vendor and
-Product ID's using module parameters for unknown scanners.  Refer to
-the document README.scanner_hp_sane for guidance on how to configure
-SANE to use a USB HP Scanner.
-
-
-ADDITIONAL INFORMATION
-
-http://www.linux-usb.org/
-http://www.dynamine.net/linux-usb/HOWTO/
-
-
-REQUIREMENTS
-
-A host with a USB port.  Ideally, either a UHCI (Intel) or OHCI
-(Compaq and others) hardware port should work.  However, I've only
-been able to really use an OHCI controller.  I did have access to a
-system with a UHCI controller but some very limited testing did not
-produce satisfactory results.  Luke Ordelmans
-<postbus@ordelmans.demon.nl> has reported success using the UHCI host
-controller with kernel 2.3.18 and a ChainTech motherboard.  Here
-lately I've been having better success with the ohci-hcd driver.  But
-since Linux USB support is still in a state of constant development
-that may change at a later date.  I am confident that eventually all
-the host contollers will perform without incident.
-
-A Linux kernel with USB support (preferably linux-2.3.18+)
-
-A Linux kernel with USB Scanner support.
-
-
-CONFIGURATION
-
-Using `make menuconfig` or your prefered method for configuring the
-kernel, select 'Support for USB', 'OHCI/OHCI-HCD/UHCI' depending on
-your hardware, 'USB hub support', and 'USB Scanner support'.  Compile
-and install the modules (you may need to execute `depmod -a` to update
-the module dependencies).  Testing was performed only as modules,
-YMMV.
-
-Add a device for the USB scanner:
-  linux-2.3.22 and above: `mknod /dev/usbscanner c 180 48`
-  linux-2.3.21 and below: `mknod /dev/usbscanner c 16 1`
-
-Set appropriate permissions for /dev/usbscanner (don't forget about
-group and world permissions).  Both read and write permissions are
-required for proper operation.
-
-Load the appropriate modules (if compiled as modules):
-
-  OHCI:
-    modprobe usb-ohci
-    modprobe scanner
-
-  OHCI-HCD:
-    modprobe usb-ohci-hcd
-    modprobe hub
-    modprobe scanner
-
-  UHCI:
-    modprobe usb-uhci
-    modprobe hub (don't know if this is required or not)
-    modprobe scanner
-
-That's it.  SANE should now be able to access the device.  
-
-There is a small test program (hp_scan.c -- appended below) that can
-be used to test the scanner device if it's an HP scanner that supports
-SCL.  Its purpose is to test the driver without having to
-retrieve/configure SANE.  Hp_scan.c will scan the entire bed and put
-the output into a file called 'out.dat' in the current directory.  The
-data in the file is raw data so it's not very useful for imaging.
-
-
-MODULE PARAMETERS
-
-If you have a device that wish to experiment with or try using this
-driver with, but the Vendor and Product ID's are not coded in, don't
-despair.  If the driver was compiled as a module, you can pass options
-to the driver.  Simply add 'options scanner vendor=0x####
-product=0x****' to the conf.modules/modules.conf file replacing the
-#'s and the *'s with the correct ID's.  The ID's can be retrieved from
-the messages file or using `cat /proc/bus/usb/devices` if USB /proc
-support was selected during kernel configuration.
-
-
-BUGS
-
-If you encounter any problems feel free to drop me an email.
-
-David /\/elson
-dnelson@jump.net
-http://www.jump.net/~dnelson
-
---------------- snip -- hp_scan.c -- snip ---------------
-/*
-
-This is a really crude attempt at writing a short test program.  It's
-mostly only to be used to test connectivity with USB HP scanners that
-understand SCL.  Currently, the supported models are 4100C, 5200C,
-6200C, and the 6300C.  Note that the 4200C is *NOT* acceptable.
-
-Copyright (C) David E. Nelson <dnelson@jump.net>, 1999
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <error.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-/*
-   Gray Output produces about a 8945400 byte file.
-   Color Output produces a 26836200 byte file. 
-   
-   To compile: gcc -o hp_scan hp_scan.c
-*/
-
-// #define COLOR /* Undef to scan GrayScale */
-
-int send_cmd(int, const char *, int);
-int read_cmd(int, char *, int);
-
-int
-main(void) {
-
-       ssize_t cnt = 0, total_cnt = 0;
-
-       FILE *fpout;
-
-       int fp;
-       int data_size = 32768;
-
-       char *data;
-
-       static char reset_cmd[] = {'\x1b','E'};
-
-#ifdef COLOR
-       static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */
-       static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */
-#else
-       static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */
-       static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */
-#endif
-
-       static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'};
-       static char start_scan_cmd[] = {'\x1b','*','f','0','S'};
-       
-       if(!(data=malloc(data_size))) {
-               perror("malloc failed");
-               exit (1);
-       }
-       
-       if((fp=open("/dev/usbscanner", O_RDWR)) < 0) {
-               perror("Unable to open scanner device");
-               exit (1);
-       }
-
-       if((fpout=fopen("out.dat", "w+")) == NULL) {
-               perror("Unable to open ouput file");
-               exit(1);
-       }
-
-       send_cmd(fp, reset_cmd, sizeof(reset_cmd));
-       send_cmd(fp, data_type_cmd, sizeof(data_type_cmd));
-       send_cmd(fp, data_width_cmd, sizeof(data_width_cmd));
-       send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd));
-
-       while ((cnt = read(fp, data, data_size)) > 0) {
-               printf("Read: %u\n", cnt); 
-               if(fwrite(data, sizeof(char), cnt, fpout) < 0) {
-                       perror("Write to output file failed");
-                       exit (1);
-               }
-               total_cnt += cnt;
-       }
-       if (cnt < 0) {
-               perror("Read from scanner failed");
-               exit (1);
-       }
-
-       printf("\nRead %lu bytes.\n", total_cnt);
-
-       send_cmd(fp, reset_cmd, sizeof(reset_cmd));
-
-       close(fp);
-       fclose(fpout);
-       return (0);
-}
-
-int
-send_cmd(int fp, const char * cmd, int length) {
-
-       int result;
-       int x;
-
-       if((result = write(fp, cmd, length)) != length) {
-               printf ("Write warning: %d bytes requested, %d written\n");
-       } else if (result < 0) {
-               perror ("send_cmd failure");
-               exit (1);
-       }
-       return (result);
-}
-       
-int
-read_cmd(int fp, char * response, int length) {
-
-       return read(fp, response, length);
-
-}
diff --git a/drivers/usb/README.scanner_hp_sane b/drivers/usb/README.scanner_hp_sane
deleted file mode 100644 (file)
index 220bbb2..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-Oct. 19, 1999
-
-CHANGES
-
-- Ammended for Linux-2.3.22+
-
-
-INTRODUCTION
-
-This document will hopefully provide enough info on how to get SANE
-working with a Hewlett Packard USB capable scanner using the USB
-interface.  The majority of HP Scanners support the Scanner Control
-Language (SCL) which is both published by HP and supported by SANE.
-The only HP Scanner that I'm aware of that does not support SCL is the
-4200C.  All other HP scanners with USB interfaces should work (4100C,
-5200C, 6200C, and 6300C).  Of course as HP releases new scanners this
-information may change.
-
-
-REQUIREMENTS
-
-In order to get this running you'll need USB support in your kernel in
-addition to USB Scanner support.  Please refer to README.scanner
-for issues pertaining to Linux USB and USB Scanner support.
-
-An installed version of SANE which is available from
-http://www.mostang.com/sane/.  Testing has been performed using
-version SANE-1.0.1.  For instructions on building and installing SANE,
-refer to the various README files within the SANE distribution.
-
-
-OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW?
-
-NOTE: $INSTALL_DIR is the location where SANE was installed.  It may
-be /usr/local, /usr, /opt or somewhere else.  If you don't know, ask
-your system administrator.
-
-1) Make sure that you have the libsane-hp.* libraries under the
-$INSTALL_DIR/lib/sane/ directory.  If you don't, then the HP backend
-was either not compiled or installed properly.
-
-2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following
-files: dll.conf, hp.conf.
-
-  dll.conf:  Make sure that the 'hp' entry is present and uncommented.
-
-  hp.conf: This should contain two lines:
-
-    /dev/usbscanner
-    option connect-device
-
-3) You should now be able to use SANE (xscanimage or scanimage).
-
-Don't forget to read any relevant man pages regarding the usage of
-SANE.  If you have other entries uncommented in dll.conf, you may have
-to specify the device to (x)scanimage.  Again, `man` is your friend.
-The xscanimage (1) man page has info on how to get 'The Gimp' to work
-with xscanimage.  Note that Gimp support must be compiled into SANE
-for it work.  If you are dealing with a RedHat system, this means that
-you'll also need to install the gimp-devel rpm package.
-
-NOTE: The issues regarding core dumping by (x)scanimage have (or seem
-to be thus far) been resolved with version 0.2+ of the USB scanner
-driver which should be available in linux-2.3.23.  If you notice
-otherwise, please contact me.
-
-David /\/elson
-dnelson@jump.net
-http://www.jump.net/~dnelson
diff --git a/drivers/usb/README.serial b/drivers/usb/README.serial
deleted file mode 100644 (file)
index 053f18d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-This serial driver currently only works with the Belkin and Peracom USB 
-Serial devices. It should also work for the Etek converter, but I do 
-not know the vendor id and device id of that device (if anyone does, 
-please let me know.)
-
-If your device is not compatible with the above models, you can try
-out the "generic" interface. This interface does not provide any type
-of control messages sent to the device, and does not support any kind
-of device flow control. All that is required of your device is that
-it has at least one bulk in endpoint, or one bulk out endpoint.
-To enable the driver to recognize your device, build the driver as
-a module and load it by the following invocation:
-       insmod usb-serial.o vendor=0x#### product=0x####
-where the #### is replaced with the hex representation of your device's
-vendor id and product id.
-
-The driver can handle enumerating the device, and sending and receiving
-data from the converter. However, since I do not have a spec for the Belkin,
-Peracom, and eTek devices, and the raw dumps from the Win98 driver are 
-confusing, and eTek keeps giving me the run around, no control signals are 
-currently handled, and the data will most likely come through on a baud
-rate that you are not expecting. So if you have these devices, do not 
-expect the correct data to show up at either end. 
-
-The major number that the driver uses is 188 so to use the driver, create
-the following nodes:
-mknod /dev/ttyUSB0 c 188 0
-mknod /dev/ttyUSB1 c 188 1
-mknod /dev/ttyUSB2 c 188 2
-mknod /dev/ttyUSB3 c 188 3
-
-then plug in a device and use your friendly terminal program to see what
-happens.
-
-If anyone has any problems getting the device to enumerate, or data to 
-flow through it, please contact me.
-
-
-
-greg k-h
-greg@kroah.com
-
diff --git a/drivers/usb/README.uhci b/drivers/usb/README.uhci
deleted file mode 100644 (file)
index 53aaa11..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-Specification and Internals for the New UHCI Driver (Whitepaper...)
-
-       brought to you by
-
-       Georg Acher, acher@in.tum.de (executive slave) (base guitar)
-       Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
-       Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
-       $Id: README.uhci,v 1.1 1999/12/14 14:03:02 fliegl Exp $
-
-This document and the new uhci sources can be found on
-               http://hotswap.in.tum.de/usb
-
-1. General issues
-
-1.1 Why a new UHCI driver, we already have one?!?
-
-Correct, but its internal structure got more and more mixed up by the (still
-ongoing) efforts to get isochronous transfers (ISO) to work.
-Since there is an increasing need for reliable ISO-transfers (especially 
-for USB-audio needed by TS and for a DAB-USB-Receiver build by GA and DF), 
-this state was a bit unsatisfying in our opinion, so we've decided (based
-on knowledge and experiences with the old UHCI driver) to start 
-from scratch with a new approach, much simpler but at the same time more 
-powerful.
-It is inspired by the way Win98/Win2000 handles USB requests via URBs,
-but it's definitely 100% free of MS-code and doesn't crash while 
-unplugging an used ISO-device like Win98 ;-)
-Some code for HW setup and root hub management was taken from the 
-original UHCI driver, but heavily modified to fit into the new code.
-The invention of the basic concept, and major coding were completed in two 
-days (and nights) on the 16th and 17th of October 1999, now known as the
-great USB-October-Revolution started by GA, DF, and TS ;-)
-
-Since the concept is in no way UHCI dependant, we hope that it will also be 
-transfered to the OHCI-driver, so both drivers share a common API.
-
-1.2. Advantages and disadvantages
-
-+ All USB transfer types work now!
-+ Asynchronous operation
-+ Simple, but powerful interface (only two calls for start and cancel)
-+ Easy migration to the new API, simplified by a compatibility API
-+ Simple usage of ISO transfers
-+ Automatic linking of requests
-+ ISO transfers allow variable length for each frame and striping
-+ No CPU dependent and non-portable atomic memory access, no asm()-inlines
-+ Tested on x86 and Alpha
-
-- Rewriting for ISO transfers needed
-
-1.3. Is there some compatibility to the old API?
-
-Yes, but only for control, bulk and interrupt transfers. We've implemented 
-some wrapper calls for these transfer types. The usbcore works fine with 
-these wrappers. For ISO there's no compatibility, because the old ISO-API 
-and its semantics were unnecessary complicated in our opinion.
-
-1.4. What's really working?
-
-As said above, CTRL und BULK already work fine even with the wrappers,
-so legacy code wouldn't notice the change.
-Regarding to Thomas, ISO transfers now run stable with USB audio.
-INT transfers (e.g. mouse driver) work fine, too.
-
-1.5. Are there any bugs?
-
-No ;-)
-Hm...
-Well, of course this implementation needs extensive testing on all available
-hardware, but we believe that any fixes shouldn't harm the overall concept.
-
-1.6. What should be done next?
-
-A large part of the request handling seems to be identical for UHCI and 
-OHCI, so it would be a good idea to extract the common parts and have only 
-the HW specific stuff in uhci.c. Furthermore, all other USB device drivers
-should need URBification, if they use isochronous or interrupt transfers.
-One thing missing in the current implementation (and the old UHCI driver) 
-is fair queueing for BULK transfers. Since this would need (in principle) 
-the alteration of already constructed TD chains (to switch from depth to 
-breadth execution), another way has to be found. Maybe some simple 
-heuristics work with the same effect.
-
----------------------------------------------------------------------------
-
-2. Internal structure and mechanisms
-
-To get quickly familiar with the internal structures, here's a short
-description how the new UHCI driver works. However, the ultimate source of
-truth is only uhci.c!
-
-2.1. Descriptor structure (QHs and TDs)
-
-During initialization, the following skeleton is allocated in init_skel:
-
-        framespecific           |           common chain     
-
-framelist[]
-[  0 ]-----> TD --> TD -------\
-[  1 ]-----> TD --> TD --------> TD ----> QH -------> QH -------> QH ---> NULL
-  ...        TD --> TD -------/
-[1023]-----> TD --> TD ------/
-            
-            ^^     ^^           ^^       ^^          ^^          ^^
-   1024 TDs for   7 TDs for    1 TD for   Start of    Start of    End Chain
-           ISO  INT (2-128ms) 1ms-INT    CTRL Chain  BULK Chain
-
-For each CTRL or BULK transfer a new QH is allocated and the containing data
-transfers are appended as (vertical) TDs. After building the whole QH with its
-dangling TDs, the QH is inserted before the BULK Chain QH (for CTRL) or
-before the End Chain QH (for BULK). Since only the QH->next pointers are
-affected, no atomic memory operation is required. The three QHs in the
-common chain are never equipped with TDs!
-
-For ISO or INT, the TD for each frame is simply inserted into the apropriate
-ISO/INT-TD-chain for the desired frame. The 7 skeleton INT-TDs are scattered
-among the 1024 frames similar to the old UHCI driver.
-
-For CTRL/BULK/ISO, the last TD in the transfer has the IOC-bit set. For INT,
-every TD (there is only one...) has the IOC-bit set.
-
-Besides the data for the UHCI controller (2 or 4 32bit words), the descriptors
-are double-linked through the .vertical and .horizontal elements in the 
-SW data of the descriptor (using the double-linked list structures and 
-operations), but SW-linking occurs only in closed domains, i.e. for each of
-the 1024 ISO-chains and the 8 INT-chains there is a closed cycle. This 
-simplifies all insertions and unlinking operations and avoids costly 
-bus_to_virt()-calls.
-
-2.2. URB structure and linking to QH/TDs
-
-During assembly of the QH and TDs of the requested action, these descriptors
-are stored in urb->urb_list, so the allocated QH/TD descriptors are bound to
-this URB.
-If the assembly was successful and the descriptors were added to the HW chain,
-the corresponding URB is inserted into a global URB list for this controller.
-This list stores all pending URBs.
-
-2.3. Interrupt processing
-
-Since UHCI provides no means to directly detect completed transactions, the
-following is done in each UHCI interrupt (uhci_interrupt()):
-
-For each URB in the pending queue (process_urb()), the ACTIVE-flag of the 
-associated TDs are processed (depending on the transfer type 
-process_{transfer|interrupt|iso}()). If the TDs are not active anymore, 
-they indicate the completion of the transaction and the status is calculated. 
-Inactive QH/TDs are removed from the HW chain (since the host controller
-already removed the TDs from the QH, no atomic access is needed) and 
-eventually the URB is marked as completed (OK or errors) and removed from the 
-pending queue. Then the next linked URB is submitted. After (or immediately 
-before) that, the completion handler is called.
-
-2.4. Unlinking URBs
-
-First, all QH/TDs stored in the URB are unlinked from the HW chain. 
-To ensure that the host controller really left a vertical TD chain, we 
-wait for one frame. After that, the TDs are physically destroyed.
-
-2.5. URB linking and the consequences
-
-Since URBs can be linked and the corresponding submit_urb is called in
-the UHCI-interrupt, all work associated with URB/QH/TD assembly has to be
-interrupt save. This forces kmalloc to use GFP_ATOMIC in the interrupt.
index 6072e060e1d6551ddd9579f53a16ca5070523ff3..614ab81c6b54b93819f79765145451863a811892 100644 (file)
@@ -334,7 +334,7 @@ static int sohci_submit_urb (urb_t * urb)
        /* for ISOC transfers calculate start frame index */
        if (urb->transfer_flags & USB_ISO_ASAP) { 
                urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1): 
-                                                               (ohci->hcca.frame_no + 10)) & 0xffff;
+                                                               (le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff;
        }       
        
        td_submit_urb (urb); /* fill the TDs and link it to the ed */
@@ -385,8 +385,10 @@ static int sohci_unlink_urb (urb_t * urb)
                        spin_unlock_irqrestore (&usb_ed_lock, flags);
 
                        current->state = TASK_UNINTERRUPTIBLE;
-                       schedule_timeout (HZ / 10); /* wait until all TDs are deleted */
-                       remove_wait_queue (&op_wakeup, &wait); 
+                       if(schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */
+                               remove_wait_queue (&op_wakeup, &wait); 
+                       else
+                               printk (KERN_ERR MODSTR "unlink URB timeout!\n");
                } else 
                        urb_rm_priv (urb);
                usb_dec_dev_use (urb->dev);             
@@ -463,7 +465,7 @@ static int sohci_get_current_frame_number (struct usb_device *usb_dev)
 {
        ohci_t * ohci = usb_dev->bus->hcpriv;
        
-       return ohci->hcca.frame_no;
+       return le16_to_cpu (ohci->hcca.frame_no);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -775,7 +777,7 @@ static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed)
        writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
        writel (OHCI_INTR_SF, &ohci->regs->intrenable); /* enable sof interrupt */
 
-       frame = ohci->hcca.frame_no & 0x1;
+       frame = le16_to_cpu (ohci->hcca.frame_no) & 0x1;
        ed->ed_rm_list = ohci->ed_rm_list[frame];
        ohci->ed_rm_list[frame] = ed;
 
@@ -1486,7 +1488,7 @@ static int hc_start (ohci_t * ohci)
        writel (0, &ohci->regs->ed_controlhead);
        writel (0, &ohci->regs->ed_bulkhead);
        
-       writel (virt_to_bus(&ohci->hcca), &ohci->regs->hcca); /* a reset clears this */
+       writel (virt_to_bus (&ohci->hcca), &ohci->regs->hcca); /* a reset clears this */
    
        fminterval = 0x2edf;
        writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
@@ -1527,14 +1529,14 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
        struct ohci_regs * regs = ohci->regs;
        int ints; 
 
-       if ((ohci->hcca.done_head != 0) && !(ohci->hcca.done_head & 0x01)) {
+       if ((ohci->hcca.done_head != 0) && !(le32_to_cpu (ohci->hcca.done_head) & 0x01)) {
                ints =  OHCI_INTR_WDH;
        } else { 
                if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0)
                        return;
        } 
 
-       dbg (KERN_DEBUG MODSTR "Interrupt: %x frame: %x \n", ints, ohci->hcca.frame_no);
+       dbg (KERN_DEBUG MODSTR "Interrupt: %x frame: %x \n", ints, le16_to_cpu (ohci->hcca.frame_no));
        
        if (ints & OHCI_INTR_WDH) {
                writel (OHCI_INTR_WDH, &regs->intrdisable);     
@@ -1548,7 +1550,7 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
        }
 
        if (ints & OHCI_INTR_SF) { 
-               unsigned int frame = (ohci->hcca.frame_no) & 1;
+               unsigned int frame = le16_to_cpu (ohci->hcca.frame_no) & 1;
                writel (OHCI_INTR_SF, &regs->intrdisable);      
                if (ohci->ed_rm_list[!frame] != NULL) {
                        dl_del_list (ohci, !frame);
index e9ea434bd76a1c1ab308bd010e6daf7ce6733800..39fb1c0d9b802f83f717bf3fb286116bddc03cf8 100644 (file)
  * Version History:
  *    Version 1.00 - Initial version
  */
+
+/*
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 #define __NO_VERSION__
 
 #include "usb.h"
 #include "ov511.h"
 
+#define OV511_I2C_RETRIES 3
+
 /* Video Size 384 x 288 x 3 bytes for RGB */
-#define MAX_FRAME_SIZE (384 * 288 * 3)
+#define MAX_FRAME_SIZE (320 * 240 * 3)
 
 // FIXME - Force CIF to make some apps happy for the moment. Should find a 
 //         better way to do this.
-#define DEFAULT_WIDTH 384
-#define DEFAULT_HEIGHT 288
+#define DEFAULT_WIDTH 320
+#define DEFAULT_HEIGHT 240
 
 char kernel_version[] = UTS_RELEASE;
 
@@ -173,7 +190,7 @@ static void rvfree(void *mem, unsigned long size)
        vfree(mem);
 }
 
-int usb_ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value)
+int ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value)
 {
        int rc;
 
@@ -183,13 +200,13 @@ int usb_ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char
                USB_TYPE_CLASS | USB_RECIP_DEVICE,
                0, (__u16)reg, &value, 1, HZ);  
                        
-       PDEBUG("reg write: 0x%X:0x%X\n", reg, value);
+       PDEBUG("reg write: 0x%02X:0x%02X\n", reg, value);
                        
        return rc;
 }
 
 /* returns: negative is error, pos or zero is data */
-int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg)
+int ov511_reg_read(struct usb_device *dev, unsigned char reg)
 {
        int rc;
        unsigned char buffer[1];
@@ -200,7 +217,7 @@ int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg)
                USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
                0, (__u16)reg, buffer, 1, HZ);
                                
-       PDEBUG("reg read: 0x%X:0x%X\n", reg, buffer[0]);
+       PDEBUG("reg read: 0x%02X:0x%02X\n", reg, buffer[0]);
        
        if(rc < 0)
                return rc;
@@ -208,89 +225,116 @@ int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg)
                return buffer[0];       
 }
 
-int usb_ov511_cam_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value)
+int ov511_i2c_write(struct usb_device *dev, unsigned char reg, unsigned char value)
 {
-       int rc;
-       
-       // Three byte write cycle
-       
-       //    Set slave ID (This might only need to be done once)
-       //    (CAMERA SPECIFIC (OV7610/OV7110))
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
-                                OV7610_I2C_WRITE_ID);
-       if (rc < 0) return rc;
-       
-       //    Select camera register (I2C sub-address)
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
-       if (rc < 0) return rc;
+       int rc, retries;
 
-       //    Write "value" to I2C data port of OV511
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);  
-       if (rc < 0) return rc;
-       
-       // FIXME - should ensure bus is idle before continuing
-       
-       //    Initiate 3-byte write cycle
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);     
+       PDEBUG("i2c write: 0x%02X:0x%02X\n", reg, value);
+       /* Three byte write cycle */
+       for(retries = OV511_I2C_RETRIES;;) {
+               /* Select camera register */
+               rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
+               if (rc < 0) return rc;
 
-       return rc;
+               /* Write "value" to I2C data port of OV511 */
+               rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);      
+               if (rc < 0) return rc;
+
+               /* Initiate 3-byte write cycle */
+               rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);
+               if (rc < 0) return rc;
+
+               do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
+               while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+               if (rc < 0) return rc;
+
+               if((rc&2) == 0) /* Ack? */
+                       break;
+
+               /* I2C abort */ 
+               ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
+
+               if (--retries < 0) return -1;
+       }
+
+       return 0;
 }
 
 /* returns: negative is error, pos or zero is data */
-int usb_ov511_cam_reg_read(struct usb_device *dev, unsigned char reg)
+int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
 {
-       int rc;
+       int rc, value, retries;
 
-       // Two byte write cycle
-       
-       //    Set slave ID (This might only need to be done once)
-       //    (CAMERA SPECIFIC (OV7610/OV7110))
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,                                      OV7610_I2C_WRITE_ID);
-       if (rc < 0) return rc;
-       
-       //    Select camera register (I2C sub-address)
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);   
-       if (rc < 0) return rc;
-       
-       //    Initiate 2-byte write cycle
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);     
-       if (rc < 0) return rc;
-       
-       // Two byte read cycle
-       
-       //    Set slave ID (This might only need to be done once)
-       //    (CAMERA SPECIFIC (OV7610/OV7110))
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
-                                OV7610_I2C_READ_ID);
-       if (rc < 0) return rc;
-       
-       //    Initiate 2-byte read cycle
-       rc = usb_ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);     
+       /* Two byte write cycle */
+       for(retries = OV511_I2C_RETRIES;;) {
+               /* Select camera register */
+               rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
+               if (rc < 0) return rc;
+
+               /* Initiate 2-byte write cycle */
+               rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);
+               if (rc < 0) return rc;
+
+               do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
+               while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+               if (rc < 0) return rc;
+
+               if((rc&2) == 0) /* Ack? */
+                       break;
+
+               /* I2C abort */ 
+               ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
+
+               if (--retries < 0) return -1;
+       }
+
+       /* Two byte read cycle */
+       for(retries = OV511_I2C_RETRIES;;) {
+               /* Initiate 2-byte read cycle */
+               rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
+               if (rc < 0) return rc;
+
+               do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
+               while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+               if (rc < 0) return rc;
+
+               if((rc&2) == 0) /* Ack? */
+                       break;
+
+               /* I2C abort */ 
+               rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
+               if (rc < 0) return rc;
+
+               if (--retries < 0) return -1;
+       }
+
+       value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
+       PDEBUG("i2c read: 0x%02X:0x%02X\n", reg, value);
+               
+       /* This is needed to make ov511_i2c_write() work */
+       rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
        if (rc < 0) return rc;
        
-       // FIXME - should check I2C bus status here before reading data!
-       
-       //    Write "value" to I2C data port of OV511
-       return usb_ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);        
+       return (value);
 }
 
-int usb_ov511_reset(struct usb_device *dev, unsigned char reset_type)
+int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
        int rc;
        
        PDEBUG("Reset: type=0x%X\n", reset_type);
-       rc = usb_ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
+       rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
        if (rc < 0)
                printk(KERN_ERR "ov511: reset: command failed\n");
 
-       rc = usb_ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
+       rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
        if (rc < 0)
                printk(KERN_ERR "ov511: reset: command failed\n");
 
        return rc;
 }
 
-int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
+int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
 {
        int alt, multiplier, err;
                
@@ -303,7 +347,7 @@ int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
                        break;
                case 993:
                        alt = 1;
-                       multiplier = 32;
+                       multiplier = 31;
                        break;
                case 768:
                        alt = 2;
@@ -311,7 +355,7 @@ int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
                        break;
                case 769:
                        alt = 3;
-                       multiplier = 25;
+                       multiplier = 24;
                        break;
                case 512:
                        alt = 4;
@@ -319,11 +363,11 @@ int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
                        break;
                case 513:
                        alt = 5;
-                       multiplier = 17;
+                       multiplier = 16;
                        break;
                case 257:
                        alt = 6;
-                       multiplier = 9;
+                       multiplier = 8;
                        break;
                case 0:
                        alt = 7;
@@ -335,7 +379,7 @@ int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
                        return -EINVAL;
        }
 
-       err = usb_ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
+       err = ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
                                  multiplier);
        if (err < 0) {
                printk(KERN_ERR "ov511: Set packet size: Set FIFO size ret %d\n",
@@ -349,7 +393,7 @@ int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
        }
 
        // FIXME - Should we only reset the FIFO?
-       if (usb_ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0)
+       if (ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0)
                return -ENOMEM;
 
        return 0;
@@ -358,43 +402,85 @@ int usb_ov511_set_packet_size(struct usb_ov511 *ov511, int size)
 /* How much data is left in the scratch buf? */
 #define scratch_left(x)        (ov511->scratchlen - (int)((char *)x - (char *)ov511->scratch))
 
-// FIXME - Useless stub
-static void ov511_parse_data(struct usb_ov511 *ov511)
-{
-       PDEBUG("ov511_parse_data not implemented\n"); // TEMPORARY CODE
-}
-
-static int ov511_compress_isochronous(struct usb_ov511 *ov511, urb_t *urb)
+static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
 {
-       unsigned char *cdata, *data;
+       unsigned char *cdata;
        int i, totlen = 0;
+       int aPackNum[10];
+       struct ov511_frame *frame;
+
+       if (ov511->curframe == -1) {
+         return 0;
+       }
 
-       data = ov511->scratch + ov511->scratchlen;
        for (i = 0; i < urb->number_of_packets; i++) {
                int n = urb->iso_frame_desc[i].actual_length;
                int st = urb->iso_frame_desc[i].status;
                
                cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
-               if (st) { 
+               if (!n) continue;
+
+               aPackNum[i] = n ? cdata[512] : -1;
+
+               if (st){ 
                        // Macro - must be in braces!
                        PDEBUG("data error: [%d] len=%d, status=%d\n",
                                i, n, st);
-                }
+               }
+
+               frame = &ov511->frame[ov511->curframe];
+               
+               /* Can we find a frame end */
+               if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
+                    cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
+                   (cdata[8] & 8) && (cdata[8] & 0x80)) {
+
+                   PDEBUG("Found Frame End!, packnum = %d\n", (int)(cdata[512]));
+                   PDEBUG("Current frame = %d\n", ov511->curframe);
+
+                   if (frame->scanstate == STATE_LINES) {
+                       if (waitqueue_active(&frame->wq)) {
+                         PDEBUG("About to wake up waiting processes\n");
+                         frame->grabstate = FRAME_DONE;
+                         wake_up_interruptible(&frame->wq);
+                       }
+                   }
+               }
 
-               if ((ov511->scratchlen + n) > SCRATCH_BUF_SIZE) {
-                       PDEBUG("scratch buf overflow!scr_len: %d, n: %d\n", ov511->scratchlen, n );
-                       return totlen;
+               /* Can we find a frame start */
+               else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
+                         cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
+                        (cdata[8] & 8)) {
+                   PDEBUG("ov511: Found Frame Start!, packnum = %d\n", (int)(cdata[512]));
+                   frame->scanstate = STATE_LINES;
+                   frame->curpix = 0;
                }
 
-               if (n) {
-                       memmove(data, cdata, n);
-                       data += n;
-                       totlen += n;
-                       ov511->scratchlen += n;
+               /* Are we in a frame? */
+               else if (frame->scanstate == STATE_LINES) {
+                 unsigned char *f = frame->data + 3 * frame->curpix;
+                 int i;
+                 if (frame->curpix <= 320 * 240 - 256) {
+                   for (i=0; i<256; i++) {
+                     *f++ = *cdata;
+                     *f++ = *cdata;
+                     *f++ = *cdata++;
+                     *f++ = *cdata;
+                     *f++ = *cdata;
+                     *f++ = *cdata++;
+                   }
+                   frame->curpix += 512;
+                 } else {
+                   PDEBUG("Too many pixels!\n");
+                 }
                }
+
        }
 
+       PDEBUG("pn: %d %d %d %d %d %d %d %d %d %d\n",
+              aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
+              aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
        return totlen;
 }
 
@@ -405,7 +491,17 @@ static void ov511_isoc_irq(struct urb *urb)
        struct ov511_sbuf *sbuf;
        int i;
 
-       PDEBUG("ov511_isoc_irq: %p status %d, errcount = %d, length = %d\n", urb, urb->status, urb->error_count, urb->actual_length);
+#if 0
+       static int last_status, last_error_count, last_actual_length;
+       if (last_status != urb->status ||
+           last_error_count != urb->error_count ||
+           last_actual_length != urb->actual_length) {
+         PDEBUG("ov511_isoc_irq: %p status %d, errcount = %d, length = %d\n", urb, urb->status, urb->error_count, urb->actual_length);
+         last_status = urb->status;
+         last_error_count = urb->error_count;
+         last_actual_length = urb->actual_length;
+       }
+#endif
 
        if (!ov511->streaming) {
                PDEBUG("hmmm... not streaming, but got interrupt\n");
@@ -413,11 +509,10 @@ static void ov511_isoc_irq(struct urb *urb)
        }
        
        sbuf = &ov511->sbuf[ov511->cursbuf];
-//     usb_kill_isoc(sbuf->isodesc);
 
        /* Copy the data received into our scratch buffer */
-       len = ov511_compress_isochronous(ov511, urb);
-
+       len = ov511_move_data(ov511, urb);
+#if 0
        /* If we don't have a frame we're current working on, complain */
        if (ov511->scratchlen) {
                if (ov511->curframe < 0) {
@@ -426,7 +521,7 @@ static void ov511_isoc_irq(struct urb *urb)
                } else
                        ov511_parse_data(ov511);
        }
-
+#endif
        for (i = 0; i < FRAMES_PER_DESC; i++) {
                sbuf->urb->iso_frame_desc[i].status = 0;
                sbuf->urb->iso_frame_desc[i].actual_length = 0;
@@ -435,9 +530,6 @@ static void ov511_isoc_irq(struct urb *urb)
        /* Move to the next sbuf */
        ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
 
-       /* Reschedule this block of Isochronous desc */
-//     usb_run_isoc(sbuf->isodesc, ov511->sbuf[ov511->cursbuf].isodesc);
-
        return;
 }
 
@@ -452,9 +544,25 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
        ov511->cursbuf = 0;
        ov511->scratchlen = 0;
 
-       // FIXME - is this the proper size?
-       usb_ov511_set_packet_size(ov511, 512);
+       ov511_set_packet_size(ov511, 512);
        
+#define OV511_COLOR_BAR_TEST
+#ifdef OV511_COLOR_BAR_TEST
+       {
+         int rc;
+         rc = ov511_i2c_read(ov511->dev, 0x12);
+         rc = ov511_i2c_write(ov511->dev, 0x12, 0x3f);
+         rc = ov511_i2c_read(ov511->dev, 0x12);
+         rc = ov511_i2c_read(ov511->dev, 0x13);
+         rc = ov511_i2c_write(ov511->dev, 0x14, 0x4);
+         rc = ov511_i2c_read(ov511->dev, 0x14);
+         rc = ov511_i2c_write(ov511->dev, 0x28, 0x60);
+         rc = ov511_i2c_read(ov511->dev, 0x28);
+         ov511_reg_write(ov511->dev, OV511_REG_CAMERA_DATA_INPUT_SELECT,
+                             0);
+       }
+#endif
+
        /* We double buffer the Iso lists */
        urb = usb_alloc_urb(FRAMES_PER_DESC);
        
@@ -494,7 +602,7 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
                urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;
                urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
        }
-       
+
        ov511->sbuf[1].urb->next = ov511->sbuf[0].urb;
        ov511->sbuf[0].urb->next = ov511->sbuf[1].urb;
 
@@ -509,7 +617,7 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
 
        ov511->streaming = 1;
 
-       return 0; 
+       return 0;
 }
 
 
@@ -518,14 +626,7 @@ static void ov511_stop_isoc(struct usb_ov511 *ov511)
        if (!ov511->streaming)
                return;
 
-// FIXME - Figure out how to do this with the ov511 (Does the below do it?)
-//     /* Turn off continuous grab */
-//     if (usb_cpia_set_grab_mode(cpia->dev, 0) < 0) {
-//             printk(KERN_ERR "cpia_set_grab_mode error\n");
-//             return /* -EBUSY */;
-//     }
-
-       usb_ov511_set_packet_size(ov511, 0);
+       ov511_set_packet_size(ov511, 0);
        
        /* Unschedule all of the iso td's */
        usb_unlink_urb(ov511->sbuf[1].urb);
@@ -570,25 +671,8 @@ static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
                height = DEFAULT_HEIGHT;
        height = (height / 4) * 4;      /* Multiple of 4 */
        
-// FIXME - Don't know how to implement the equivalent of this for the ov511
-//     /* Set the ROI they want */
-//     if (usb_cpia_set_roi(cpia->dev, 0, width / 8, 0, height / 4) < 0)
-//             return -EBUSY;
-
-//     if (usb_cpia_set_compression(cpia->dev, cpia->compress ?
-//                     COMP_AUTO : COMP_DISABLED, DONT_DECIMATE) < 0) {
-//             printk(KERN_ERR "cpia_set_compression error\n");
-//             return -EBUSY;
-//     }
-
-       /* We want a fresh frame every 30 we get */
-       ov511->compress = (ov511->compress + 1) % 30;
-
-//     /* Grab the frame */
-//     if (usb_cpia_upload_frame(cpia->dev, WAIT_FOR_NEXT_FRAME) < 0) {
-//             printk(KERN_ERR "cpia_upload_frame error\n");
-//             return -EBUSY;
-//     }
+//     /* We want a fresh frame every 30 we get */
+//     ov511->compress = (ov511->compress + 1) % 30;
 
        return 0;
 }
@@ -1061,48 +1145,69 @@ static struct video_device ov511_template = {
        0
 };
 
-static int usb_ov511_configure(struct usb_ov511 *ov511)
+static int ov511_configure(struct usb_ov511 *ov511)
 {
        struct usb_device *dev = ov511->dev;
        int temprc;   // DEBUG CODE
-       
+
        /* Set altsetting 0 */
        if (usb_set_interface(dev, ov511->iface, 0) < 0) {
                printk(KERN_ERR "ov511: usb_set_interface error\n");
                return -EBUSY;
        }
-       
+
        memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
 
        init_waitqueue_head(&ov511->frame[0].wq);
        init_waitqueue_head(&ov511->frame[1].wq);
-       
+
        if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) {
                printk(KERN_ERR "ov511: video_register_device failed\n");
                return -EBUSY;
        }
 
-       // Disable compression
-       if (usb_ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0) {
-               printk(KERN_ERR "ov511: disable compression: command failed\n");
+       /* Reset in case driver was unloaded and reloaded without unplug */
+       if (ov511_reset(dev, OV511_RESET_ALL) < 0)
                goto error;
-       }
-       
-       // Initialize system
-       // FIXME - This should be moved to a function
-       if (usb_ov511_reg_write(dev, OV511_REG_SYSTEM_INIT, 0x01) < 0) {
+
+       /* Initialize system */
+       if (ov511_reg_write(dev, OV511_REG_SYSTEM_INIT, 0x01) < 0) {
                printk(KERN_ERR "ov511: enable system: command failed\n");
                goto error;
        }
+
+       /* This seems to be necessary */
+       if (ov511_reset(dev, OV511_RESET_ALL) < 0)
+               goto error;
+
+       /* Disable compression */
+       if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0) {
+               printk(KERN_ERR "ov511: disable compression: command failed\n");
+               goto error;
+       }
+
+// FIXME - error checking needed
+       ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
+                            OV7610_I2C_WRITE_ID);
+       ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
+                            OV7610_I2C_READ_ID);
+
+// DEBUG CODE
+//     usb_ov511_reg_write(dev, OV511_REG_I2C_CLOCK_PRESCALER,
+//                                              OV511_I2C_CLOCK_PRESCALER);
        
-       if (usb_ov511_reset(dev, OV511_RESET_NOREGS) < 0)
+       if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
                goto error;
        
+       /* Dummy read to sync I2C */
+       ov511_i2c_read(dev, 0x1C);
+       
 // DEBUG - TEST CODE FOR CAMERA REG READ
-       temprc = usb_ov511_cam_reg_read(dev, 0x1D);
-       PDEBUG("Camera reg 0x1D: 0x%X\n", temprc);
-// END DEBUG CODE
+       temprc = ov511_i2c_read(dev, 0x1C);
 
+       temprc = ov511_i2c_read(dev, 0x1D);
+// END DEBUG CODE
+       
        ov511->compress = 0;
        
        return 0;
@@ -1156,14 +1261,14 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
        ov511->dev = dev;
        ov511->iface = interface->bInterfaceNumber;
 
-       rc = usb_ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
+       rc = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
        if (rc < 0) {
                printk("ov511: Unable to read camera bridge registers\n");
                return NULL;
-       } else if (rc == 3) { // D-Link DSB-C300
+       } else if (rc == 3) {  /* D-Link DSB-C300 */
                printk("ov511: Camera is a D-Link DSB-C300\n");
                ov511->customid = 3;
-       } else if (rc == 21) { // Creative Labs WebCam 3
+       } else if (rc == 21) { /* Creative Labs WebCam 3 */
                printk("ov511: Camera is a Creative Labs WebCam 3\n");
                ov511->customid = 21;           
        } else {
@@ -1173,11 +1278,7 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
                return NULL;
        }
 
-       // Reset in case driver was unloaded and reloaded without unplug
-       if (usb_ov511_reset(dev, OV511_RESET_ALL) < 0)
-               return NULL;
-       
-       if (!usb_ov511_configure(ov511)) {
+       if (!ov511_configure(ov511)) {
                ov511->user=0;
                init_MUTEX(&ov511->lock);       /* to 1 == available */
                return ov511;
index 0b85298027a4509d643e52e40a189a7319f0bde8..4dc7074bbfdb89b79c14b900586de661c86f5e87 100644 (file)
@@ -63,7 +63,7 @@
 /* System control register numbers */
 #define OV511_REG_SYSTEM_RESET                         0x50
 #define        OV511_RESET_UDC                         0x01
-#define        OV511_RESET_I2O                         0x02
+#define        OV511_RESET_I2C                         0x02
 #define        OV511_RESET_FIFO                        0x04
 #define        OV511_RESET_OMNICE                      0x08
 #define        OV511_RESET_DRAM_INTF           0x10
 #define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
 
 #define FRAMES_PER_DESC                10  /* FIXME - What should this be? */
-#define FRAME_SIZE_PER_DESC    960     /* FIXME - Shouldn't be hardcoded */
+#define FRAME_SIZE_PER_DESC    512     /* FIXME - Shouldn't be hardcoded */
 
 // FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)?
 #define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */
 // FIXME - these can vary between specific models
 #define OV7610_I2C_WRITE_ID 0x42
 #define OV7610_I2C_READ_ID  0x43
+#define OV511_I2C_CLOCK_PRESCALER 0x03
 
 /* Prototypes */
 int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg);
@@ -164,6 +165,7 @@ struct ov511_frame {
        int scanstate;          /* State of scanning */
 
        int curline;            /* Line of frame we're working on */
+       int curpix;
 
        long scanlength;        /* uncompressed, raw data length of frame */
        long bytes_read;        /* amount of scanlength that has been read from *data */
index bd33fa812965f3fa47ea62c9fde183277a8408de..7963de4f83ca9104de82103c836c71ea4f7ad4db 100644 (file)
@@ -1,24 +1,22 @@
-/* Driver for USB SCSI-like devices
+/* Driver for USB Mass Storage compliant devices
  *
  * (c) 1999 Michael Gee (michael@linuxspecific.com)
- * (c) 1999 Matthew Dharm (mdharm@one-eyed-alien.net)
- *
- * This driver is schizoid  - it makes a USB device appear as both a SCSI
- * device and a character device. The latter is only available if the device
- * has an interrupt endpoint, and is used specifically to receive interrupt
- * events.
+ * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
  * In order to support various 'strange' devices, this module supports plug-in
  * device-specific filter modules, which can do their own thing when required.
  *
- * Further reference.
+ * Further reference:
  *     This driver is based on the 'USB Mass Storage Class' document. This
- *     describes in detail the transformation of SCSI command blocks to the
- *     equivalent USB control and data transfer required.
+ *     describes in detail the protocol used to communicate with such
+ *      devices.  Clearly, the designers had SCSI commands in mind when they
+ *      created this document.  The commands are all similar to commands
+ *      in the SCSI-II specification.
+ *
  *     It is important to note that in a number of cases this class exhibits
  *     class-specific exemptions from the USB specification. Notably the
  *     usage of NAK, STALL and ACK differs from the norm, in that they are
- *     used to communicate wait, failed and OK on SCSI commands.
+ *     used to communicate wait, failed and OK on commands.
  *     Also, for certain devices, the interrupt endpoint is used to convey
  *     status of a command.
  *
 #include "usb.h"
 #include "usb_scsi.h"
 
-/* direction table (what a pain) */
-
+/* direction table -- this indicates the direction of the data
+ * transfer for each command code -- a 1 indicates input
+ */
 unsigned char us_direction[256/8] = {
-
-#include "usb_scsi_dt.c"
-
+       0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, 
+       0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
 #ifdef REWRITE_PROJECT
diff --git a/drivers/usb/usb_scsi_dt.c b/drivers/usb/usb_scsi_dt.c
deleted file mode 100644 (file)
index 5d615bd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, 
-0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
index 426cecfb6da2a0e63c5d3e47c2fcb24b5c1a322a..fa7a4c7207b28dfe9fb2211cd7e2ac5908a6e4ff 100644 (file)
@@ -1598,14 +1598,13 @@ aty128fb_init(void)
 void
 aty128pci_probe(void)
 {
-    struct pci_dev *pdev;
+    struct pci_dev *pdev = NULL;
     struct fb_info_aty128 *info;
     unsigned long fb_addr, reg_addr;
     u16 tmp;
 
-    for (pdev = pci_devices; pdev; pdev = pdev->next) {
-       if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
-           (pdev->vendor == PCI_VENDOR_ID_ATI)) {
+    while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
+       if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
            struct resource *rp;
 
            /* FIXME add other known R128 device ID's */
index a3a8d8f33702cdff021cb15666244d3929c3ef1d..2e44f209a7c90b87043952d239700291666f91b6 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.133 1999/12/09 10:23:13 davem Exp $
+/*  $Id: atyfb.c,v 1.134 1999/12/23 21:32:09 geert Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *     Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -470,9 +470,6 @@ static int read_aty_sense(const struct fb_info_aty *info);
      */
 
 int atyfb_init(void);
-#ifdef CONFIG_FB_OF
-void atyfb_of_init(struct device_node *dp);
-#endif
 #ifndef MODULE
 int atyfb_setup(char*);
 #endif
@@ -3640,13 +3637,10 @@ static int __init aty_init(struct fb_info_aty *info, const char *name)
 
 int __init atyfb_init(void)
 {
-#if defined(CONFIG_FB_OF)
-    /* We don't want to be called like this. */
-    /* We rely on Open Firmware (offb) instead. */
-#elif defined(CONFIG_PCI)
-    struct pci_dev *pdev;
+#if defined(CONFIG_PCI)
+    struct pci_dev *pdev = NULL;
     struct fb_info_aty *info;
-    unsigned long addr;
+    unsigned long addr, res_start, res_size;
 #ifdef __sparc__
     extern void (*prom_palette) (int);
     extern int con_is_present(void);
@@ -3663,9 +3657,8 @@ int __init atyfb_init(void)
     u16 tmp;
 #endif
 
-    for (pdev = pci_devices; pdev; pdev = pdev->next) {
-       if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
-           (pdev->vendor == PCI_VENDOR_ID_ATI)) {
+    while ((pdev = pci_find_device(PCI_VENDOR_ID_ATY, PCI_ANY_ID, pdev))) {
+       if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
            struct resource *rp;
 
            info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
@@ -3682,6 +3675,11 @@ int __init atyfb_init(void)
            if (!addr)
                continue;
 
+           res_start = rp->start;
+           res_size = rp->end-rp->start+1;
+           if (!request_mem_region(res_start, res_size, "atyfb"))
+               continue;
+
 #ifdef __sparc__
            /*
             * Map memory-mapped registers.
@@ -3707,6 +3705,7 @@ int __init atyfb_init(void)
            if (!info->mmap_map) {
                printk("atyfb_init: can't alloc mmap_map\n");
                kfree(info);
+               release_mem_region(res_start, res_size);
                return -ENXIO;
            }
            memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
@@ -3886,6 +3885,7 @@ int __init atyfb_init(void)
 
            if(!info->ati_regbase) {
                    kfree(info);
+                   release_mem_region(res_start, res_size);
                    return -ENOMEM;
            }
 
@@ -3913,6 +3913,7 @@ int __init atyfb_init(void)
 
            if(!info->frame_buffer) {
                    kfree(info);
+                   release_mem_region(res_start, res_size);
                    return -ENXIO;
            }
 
@@ -3922,6 +3923,7 @@ int __init atyfb_init(void)
                if (info->mmap_map)
                    kfree(info->mmap_map);
                kfree(info);
+               release_mem_region(res_start, res_size);
                return -ENXIO;
            }
 
@@ -3943,6 +3945,18 @@ int __init atyfb_init(void)
            info->mmap_map[1].prot_mask = _PAGE_CACHE;
            info->mmap_map[1].prot_flag = _PAGE_E;
 #endif /* __sparc__ */
+
+#ifdef CONFIG_PMAC_PBOOK
+           if (first_display == NULL)
+               pmu_register_sleep_notifier(&aty_sleep_notifier);
+           info->next = first_display;
+           first_display = info;
+#endif
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+           if (!console_fb_info)
+               console_fb_info = &info->fb_info;
+#endif /* CONFIG_FB_COMPAT_XPMAC */
        }
     }
 
@@ -4003,114 +4017,6 @@ int __init atyfb_init(void)
     return 0;
 }
 
-#ifdef CONFIG_FB_OF
-void __init atyfb_of_init(struct device_node *dp)
-{
-    unsigned long addr;
-    u8 bus, devfn;
-    u16 cmd;
-    struct fb_info_aty *info;
-    int i;
-
-    if (device_is_compatible(dp, "ATY,264LTPro")) {
-       /* XXX kludge for now */
-       if (dp->name == 0 || strcmp(dp->name, "ATY,264LTProA") != 0
-           || dp->parent == 0)
-           return;
-       dp = dp->parent;
-    }
-    switch (dp->n_addrs) {
-       case 1:
-       case 2:
-       case 3:
-           addr = dp->addrs[0].address;
-           break;
-       case 4:
-           addr = dp->addrs[1].address;
-           break;
-       default:
-           printk("Warning: got %d adresses for ATY:\n", dp->n_addrs);
-           for (i = 0; i < dp->n_addrs; i++)
-               printk(" %08x-%08x", dp->addrs[i].address,
-                      dp->addrs[i].address+dp->addrs[i].size-1);
-           if (dp->n_addrs)
-               printk("\n");
-           return;
-    }
-
-    info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
-    if (!info) {
-       printk("atyfb_of_init: can't alloc fb_info_aty\n");
-       return;
-    }
-    memset(info, 0, sizeof(struct fb_info_aty));
-
-    info->ati_regbase_phys = 0x7ff000+addr;
-    info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
-                                                  0x1000);
-
-    if(! info->ati_regbase) {
-           printk("atyfb_of_init: ioremap() returned NULL\n");
-           kfree(info);
-           return;
-    }
-
-    info->ati_regbase_phys += 0xc00;
-    info->ati_regbase += 0xc00;
-
-    /* enable memory-space accesses using config-space command register */
-    if (pci_device_loc(dp, &bus, &devfn) == 0) {
-       pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
-       if (cmd != 0xffff) {
-           cmd |= PCI_COMMAND_MEMORY;
-           pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
-       }
-    }
-
-#ifdef __BIG_ENDIAN
-    /* Use the big-endian aperture */
-    addr += 0x800000;
-#endif
-
-    /* Map in frame buffer */
-    info->frame_buffer_phys = addr;
-    info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
-
-    if(! info->frame_buffer) {
-           printk("atyfb_of_init: ioremap() returned NULL\n");
-           kfree(info);
-           return;
-    }
-
-    if (!aty_init(info, dp->full_name)) {
-       kfree(info);
-       return;
-    }
-
-#ifdef CONFIG_PMAC_PBOOK
-    if (first_display == NULL)
-       pmu_register_sleep_notifier(&aty_sleep_notifier);
-    info->next = first_display;
-    first_display = info;
-#endif
-       
-
-#ifdef CONFIG_PMAC_PBOOK
-    if (first_display == NULL)
-       pmu_register_sleep_notifier(&aty_sleep_notifier);
-    info->next = first_display;
-    first_display = info;
-#endif
-       
-
-#ifdef CONFIG_FB_COMPAT_XPMAC
-    if (!console_fb_info)
-       console_fb_info = &info->fb_info;
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-}
-#endif /* CONFIG_FB_OF */
-
-
 #ifndef MODULE
 int __init atyfb_setup(char *options)
 {
index 48e27945bbfea3f652033e9f83b1b6c842c6d805..58a2fbb24228f41ee730da6286a89353d8cf9e58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets
  *
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
  *
  * Contributors (thanks, all!)
  *
@@ -2594,10 +2594,10 @@ static void clgen_pci_unmap (struct clgenfb_info *info)
 {
        iounmap (info->fbmem);
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
-       __release_region (&iomem_resource, info->fbmem_phys, info->size);
-       __release_region (&iomem_resource, 0xA0000, 65535);
+       release_mem_region(info->fbmem_phys, info->size);
+       release_mem_region(0xA0000, 65535);
        if (release_io_ports)
-               __release_region (&ioport_resource, 0x3C0, 32);
+               release_region(0x3C0, 32);
 #endif
 }
 #endif /* MODULE */
@@ -2679,21 +2679,20 @@ static int __init clgen_pci_setup (struct clgenfb_info *info,
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
 
-       if (!__request_region (&iomem_resource, board_addr,
-                              board_size, "clgenfb")) {
+       if (!request_mem_region(board_addr, board_size, "clgenfb")) {
                pci_write_config_word (pdev, PCI_COMMAND, tmp16);
                printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n",
                       board_addr);
                return -1;
        }
-       if (!__request_region (&iomem_resource, 0xA0000, 65535, "clgenfb")) {
+       if (!request_mem_region(0xA0000, 65535, "clgenfb")) {
                pci_write_config_word (pdev, PCI_COMMAND, tmp16);
                printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n",
                       0xA0000L);
-               __release_region(&iomem_resource, board_addr, board_size);
+               release_mem_region(board_addr, board_size);
                return -1;
        }
-       if (__request_region(&ioport_resource, 0x3C0, 32, "clgenfb"))
+       if (request_region(0x3C0, 32, "clgenfb"))
                release_io_ports = 1;
 
 #endif /* kernel > 2.3.13 */
@@ -2750,7 +2749,7 @@ static int __init clgen_zorro_find (int *key_o, int *key2_o, clgen_board_t *btyp
 static void clgen_zorro_unmap (struct clgenfb_info *info)
 {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
-       __release_region(&iomem_resource, info->board_addr, info->board_size);
+       release_mem_region(info->board_addr, info->board_size);
 #endif
        if (info->btype == BT_PICASSO4) {
                iounmap (info->board_addr);
@@ -2788,8 +2787,7 @@ static int __init clgen_zorro_setup (struct clgenfb_info *info,
        info->board_addr = board_addr = (unsigned long) cd->cd_BoardAddr;
        info->board_size = board_size = (unsigned long) cd->cd_BoardSize;
 
-       if (!__request_region(&iomem_resource, board_addr,
-                             board_size, "clgenfb")) {
+       if (!request_mem_region(board_addr, board_size, "clgenfb")) {
                printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n",
                       board_addr);
                return -1;
@@ -3023,7 +3021,7 @@ int __init clgenfb_setup(char *options) {
      */
 
 #ifdef MODULE
-MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@pobox.com>");
+MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>");
 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
 
 int init_module (void)
index b2776b6c86795de5a84b7fc5fdb53cdf77be6634..81c58092ff561e1c36ba52ebfb9bb44c46f3c8c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/video/clgenfb.h - Cirrus Logic chipset constants
  *
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
  *
  * Original clgenfb author:  Frank Neumann
  *
index 9e9875237bad7b54a2a6058a47e2f7cb5a6a6a73..9e93437b3ad7f23454c5ed9b0767e1fe05dcc60f 100644 (file)
@@ -143,15 +143,19 @@ static struct {
 #ifdef CONFIG_FB_CLGEN
        { "clgen", clgenfb_init, clgenfb_setup },
 #endif
+#ifdef CONFIG_FB_ATY
+       { "atyfb", atyfb_init, atyfb_setup },
+#endif
 #ifdef CONFIG_FB_OF
+       /*
+        * Offb must be initialized _after_ all other frame buffer devices
+        * that use PCI probing and PCI resources! [ Geert ]
+        */
        { "offb", offb_init, offb_setup },
 #endif
 #ifdef CONFIG_FB_SBUS
        { "sbus", sbusfb_init, sbusfb_setup },
 #endif
-#ifdef CONFIG_FB_ATY
-       { "atyfb", atyfb_init, atyfb_setup },
-#endif
 #ifdef CONFIG_FB_ATY128
        { "aty128fb", aty128fb_init, aty128fb_setup },
 #endif
index d020ed75254470a54e852d601382de201932a37f..d03d4660a5b2f54c03388f30381b1acffbe7c151 100644 (file)
@@ -1919,21 +1919,15 @@ imsttfb_init(void)
        /* We don't want to be called like this. */
        /* We rely on Open Firmware (offb) instead. */
 #elif defined(CONFIG_PCI)
-       struct pci_dev *pdev;
+       struct pci_dev *pdev = NULL;
        struct fb_info_imstt *p;
        __u32 addr;
        __u16 cmd;
 
-       for (pdev = pci_devices; pdev; pdev = pdev->next) {
-               if (!(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
-                     && (pdev->vendor == PCI_VENDOR_ID_IMS)))
+       while ((pdev = pci_find_device(PCI_VENDOR_ID_IMS, PCI_ANY_ID, pdev))) {
+               if ((pdev->class >> 16) != PCI_BASE_CLASS_DISPLAY)
                        continue;
-
-               pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-               if (!(cmd & PCI_COMMAND_MEMORY)) {
-                       cmd |= PCI_COMMAND_MEMORY;
-                       pci_write_config_word(pdev, PCI_COMMAND, cmd);
-               }
+               pci_enable_device(pdev);
 
                addr = pdev->resource[0].start;
                if (!addr)
index bb2863b5d6ecfd7eb714e0d7c099ef0c27dd67ca..5e1fc620a6ca9c7be69188221f4a100e57f59fd0 100644 (file)
@@ -2559,14 +2559,6 @@ static struct display_switch matroxfb_cfb32 = {
 };
 #endif
 
-static struct pci_dev* pci_find(struct pci_dev* p) {
-       
-       DBG("pci_find")
-       
-       if (p) return p->next;
-       return pci_devices;
-}
-
 static void initMatrox(WPMINFO struct display* p) {
        struct display_switch *swtmp;
 
@@ -6021,15 +6013,15 @@ static int __init matrox_init(void){
 
        if (disabled)
                return -ENXIO; 
-       while ((pdev = pci_find(pdev)) != NULL) {
+       while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
                struct board* b;
                u_int8_t rev;
                u_int16_t svid;
                u_int16_t sid;
 
                pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-               pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &svid);
-               pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &sid);
+               svid = dev->subsystem_vendor;
+               sid = dev->subsystem_device;
                for (b = dev_list; b->vendor; b++) {
                        if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
                        if (b->svid)
index d5e0c2b0455d641a1cb7d0036be0bb92ce3f6001..61ca9051757b862de0204e25cc23648a9c0d68b7 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/fb.h>
 #include <linux/selection.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #ifdef CONFIG_FB_COMPAT_XPMAC
 #include <asm/vc_ioctl.h>
 #endif
@@ -290,9 +291,6 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 }
 
 
-#ifdef CONFIG_FB_ATY
-extern void atyfb_of_init(struct device_node *dp);
-#endif /* CONFIG_FB_ATY */
 #ifdef CONFIG_FB_ATY128
 extern void aty128fb_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_ATY */
@@ -414,6 +412,13 @@ int __init offb_init(void)
     return 0;
 }
 
+
+    /*
+     *  This function is intended to go away as soon as all OF-aware frame
+     *  buffer device drivers have been converted to use PCI probing and PCI
+     *  resources. [ Geert ]
+     */
+
 static int __init offb_init_driver(struct device_node *dp)
 {
 #ifdef CONFIG_FB_ATY128
@@ -422,12 +427,6 @@ static int __init offb_init_driver(struct device_node *dp)
        return 1;
     }
 #endif
-#ifdef CONFIG_FB_ATY
-    if (!strncmp(dp->name, "ATY", 3)) {
-       atyfb_of_init(dp);
-       return 1;
-    }
-#endif /* CONFIG_FB_ATY */
 #ifdef CONFIG_FB_S3TRIO
     if (!strncmp(dp->name, "S3Trio", 6)) {
        s3triofb_init_of(dp);
@@ -506,7 +505,7 @@ static void __init offb_init_nodriver(struct device_node *dp)
        address = (u_long)*up;
     else {
        for (i = 0; i < dp->n_addrs; ++i)
-           if (dp->addrs[i].size >= len)
+           if (dp->addrs[i].size >= pitch*height*depth/8)
                break;
        if (i >= dp->n_addrs) {
            printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name);
@@ -533,17 +532,25 @@ static void offb_init_fb(const char *name, const char *full_name,
     struct fb_var_screeninfo *var;
     struct display *disp;
     struct fb_info_offb *info;
+    unsigned long res_start = address;
+    unsigned long res_size = pitch*height*depth/8;
+
+    if (!request_mem_region(res_start, res_size, "offb"))
+       return;
 
     printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
           width, height, name, address, depth, pitch);
     if (depth != 8 && depth != 16 && depth != 32) {
        printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth);
+       release_mem_region(res_start, res_size);
        return;
     }
 
     info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
-    if (info == 0)
+    if (info == 0) {
+       release_mem_region(res_start, res_size);
        return;
+    }
     memset(info, 0, sizeof(*info));
 
     fix = &info->fix;
@@ -707,6 +714,7 @@ static void offb_init_fb(const char *name, const char *full_name,
 
     if (register_framebuffer(&info->info) < 0) {
        kfree(info);
+       release_mem_region(res_start, res_size);
        return;
     }
 
index bb395339cfa73983e8c66fb35af08cbd46d274e0..e3446858d00a8efed1f1024dbeda22a867442b14 100644 (file)
@@ -921,8 +921,8 @@ static int __init pm2fb_conf(struct pm2fb_info* p){
        DPRINTK("found board: %s\n", board_table[p->board].name);
 
        p->regions.p_fb=p->regions.fb_base;
-       if (!__request_region(&iomem_resource, p->regions.p_fb,
-                             p->regions.fb_size, "pm2fb")) {
+       if (!request_mem_region(p->regions.p_fb, p->regions.fb_size,
+                               "pm2fb")) {
                printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort\n");
                return 0;
        }
@@ -933,8 +933,7 @@ static int __init pm2fb_conf(struct pm2fb_info* p){
 #else
        p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
 #endif
-       if (!__request_region(&iomem_resource, p->regions.p_regs,
-                             PM2_REGS_SIZE, "pm2fb")) {
+       if (!request_mem_region(p->regions.p_regs, PM2_REGS_SIZE, "pm2fb")) {
                printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort\n");
                UNMAP(p->regions.v_fb, p->regions.fb_size);
                return 0;
@@ -1047,7 +1046,7 @@ static int __init pm2pci_detect(struct pm2fb_info* p) {
        }
        DPRINTK("scanning PCI bus for known chipsets...\n");
 
-       for (dev = pci_devices; !pci->dev && dev; dev = dev->next) {
+       pci_for_each_dev(dev) {
                for (i = 0; pm2pci_cards[i].vendor; i++)
                        if (pm2pci_cards[i].vendor == dev->vendor &&
                            pm2pci_cards[i].device == dev->device) {
@@ -1056,6 +1055,8 @@ static int __init pm2pci_detect(struct pm2fb_info* p) {
                                DPRINTK("... found %s\n", pm2pci_cards[i].name);
                                break;
                        }
+               if (pci->dev)
+                       break;
        }
        if (!pci->dev) {
                DPRINTK("no PCI board found.\n");
@@ -2036,10 +2037,10 @@ static void pm2fb_cleanup(void) {
        pm2fb_reset(i);
 
        UNMAP(i->regions.v_fb, i->regions.fb_size);
-       __release_region(&iomem_resource, i->regions.p_fb, i->regions.fb_size);
+       release_mem_region(i->regions.p_fb, i->regions.fb_size);
 
        UNMAP(i->regions.v_regs, PM2_REGS_SIZE);
-       __release_region(&iomem_resource, i->regions.p_regs, PM2_REGS_SIZE);
+       release_mem_region(i->regions.p_regs, PM2_REGS_SIZE);
 
        if (board_table[i->board].cleanup)
                board_table[i->board].cleanup(i);
index 8650c64db6382f25d2e8ffe221a5da89e5d6051f..0830468f94f7991e2f3686e7a3a0f579850ba6ef 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/video/rivafb.c - nVidia RIVA 128/TNT/TNT2 fb driver
  *
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
  *
  * Contributors:
  *
@@ -622,12 +622,12 @@ static int __init riva_pci_register (struct pci_dev *pd,
        rinfo->ctrl_base_phys = rinfo->pd->resource[0].start;
        rinfo->fb_base_phys = rinfo->pd->resource[1].start;
 
-       __request_region(&ioport_resource, 0x3C0, 32, "rivafb");
+       request_region(0x3C0, 32, "rivafb");
 
-       if (!__request_region (&iomem_resource, rinfo->ctrl_base_phys,
-                              rinfo->base0_region_size, "rivafb") ||
-           !__request_region (&iomem_resource, rinfo->fb_base_phys,
-                              rinfo->base1_region_size, "rivafb")) {
+       if (!request_mem_region(rinfo->ctrl_base_phys,
+                               rinfo->base0_region_size, "rivafb") ||
+           !request_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size,
+                               "rivafb")) {
                printk (KERN_ERR PFX "cannot reserve MMIO region\n");
                return -ENXIO;
        }
index cd543762f447b59d03719f72645395c91c6f8ba6..7aa5e14b808ed2a4904da168944092705555e5cf 100644 (file)
@@ -1969,9 +1969,8 @@ int __init tdfxfb_init(void) {
   if(!pcibios_present()) return -ENXIO;
 #endif
 
-  for(pdev = pci_devices; pdev; pdev = pdev->next) {
+  while ((pdev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_ANY_ID, pdev))) {
     if(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
-       (pdev->vendor == PCI_VENDOR_ID_3DFX) &&
        ((pdev->device == PCI_DEVICE_ID_3DFX_BANSHEE) ||
        (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO3))) {
       char* name = pdev->device == PCI_DEVICE_ID_3DFX_BANSHEE
index cf4f9baa9c987d9973e55630b56ab1d8eaace30b..63ae5c2a1ac52a7353294fbb91f870233ed86c3a 100644 (file)
@@ -541,8 +541,7 @@ int __init vesafb_init(void)
        video_visual = (video_bpp == 8) ?
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 
-       if (!__request_region(&iomem_resource, video_base, video_size,
-                             "vesafb")) {
+       if (!request_mem_region(video_base, video_size, "vesafb")) {
                printk(KERN_ERR
                       "vesafb: abort, cannot reserve video memory at 0x%lu\n",
                        video_base);
@@ -647,7 +646,7 @@ int __init vesafb_init(void)
 
        /* request failure does not faze us, as vgacon probably has this
         * region already (FIXME) */
-       __request_region(&ioport_resource, 0x3c0, 32, "vesafb");
+       request_region(0x3c0, 32, "vesafb");
 
        if (mtrr)
                mtrr_add(video_base, video_size, MTRR_TYPE_WRCOMB, 1);
index 7c05ba331ee9d7fb6f6801df444c9362e835e13c..cfadced52c39d662eefbcd1f43c7509245670fed 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/include/video/vga.h -- standard VGA chipset interaction
  *
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
  * 
  * Copyright history from vga16fb.c:
  *     Copyright 1999 Ben Pfaff and Petr Vandrovec
index 9b014c45e6759a333367e1b2207ea233c51f5464..b88adcdc5b490ee68cef0ef3b3c3d53d18516bfd 100644 (file)
@@ -924,8 +924,7 @@ int __init vga16_init(void)
 
        printk(KERN_DEBUG "vga16fb: initializing\n");
 
-       if (!__request_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN,
-                             "vga16fb")) {
+       if (!request_mem_region(VGA_FB_PHYS, VGA_FB_PHYS_LEN, "vga16fb")) {
                printk (KERN_ERR "vga16fb: unable to reserve VGA memory, exiting\n");
                return -1;
        }
@@ -951,7 +950,7 @@ int __init vga16_init(void)
 
        /* note - does not cause failure, b/c vgacon probably still owns this 
         * region (FIXME) */
-       if (__request_region(&ioport_resource, 0x3C0, 32, "vga16fb"))
+       if (request_region(0x3C0, 32, "vga16fb"))
                release_io_ports = 1;
 
        disp.var = vga16fb_defined;
@@ -994,9 +993,9 @@ void cleanup_module(void)
 {
     unregister_framebuffer(&vga16fb.fb_info);
     iounmap(vga16fb.video_vbase);
-    __release_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN);
+    release_mem_region(VGA_FB_PHYS, VGA_FB_PHYS_LEN);
     if (release_io_ports)
-       __release_region(&ioport_resource, 0x3c0, 32);
+       release_region(0x3c0, 32);
 }
 
 #endif
index 8331e9514d3cf6e34913cab5cb33b8c7221e29a7..ed32c0e488f683a5b751fe8f6ffd27a51c350ea2 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/mm.h>
 #include <linux/locks.h>
 #include <linux/fcntl.h>
+#include <linux/malloc.h>
+#include <linux/kmod.h>
 
 #include <asm/uaccess.h>
 
@@ -299,3 +301,351 @@ int block_fsync(struct file *filp, struct dentry *dentry)
 {
        return fsync_dev(dentry->d_inode->i_rdev);
 }
+
+/*
+ * bdev cache handling - shamelessly stolen from inode.c
+ * We use smaller hashtable, though.
+ */
+
+#define HASH_BITS      6
+#define HASH_SIZE      (1UL << HASH_BITS)
+#define HASH_MASK      (HASH_SIZE-1)
+static struct list_head bdev_hashtable[HASH_SIZE];
+static spinlock_t bdev_lock = SPIN_LOCK_UNLOCKED;
+static kmem_cache_t * bdev_cachep;
+
+#define alloc_bdev() \
+        ((struct block_device *) kmem_cache_alloc(bdev_cachep, SLAB_KERNEL))
+#define destroy_bdev(bdev) kmem_cache_free(bdev_cachep, (bdev))
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+       struct block_device * bdev = (struct block_device *) foo;
+
+       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+           SLAB_CTOR_CONSTRUCTOR)
+       {
+               memset(bdev, 0, sizeof(*bdev));
+               sema_init(&bdev->bd_sem, 1);
+       }
+}
+
+void bdev_init(void)
+{
+       int i;
+       struct list_head *head = bdev_hashtable;
+
+       i = HASH_SIZE;
+       do {
+               INIT_LIST_HEAD(head);
+               head++;
+               i--;
+       } while (i);
+
+       bdev_cachep = kmem_cache_create("bdev_cache",
+                                        sizeof(struct block_device),
+                                        0, SLAB_HWCACHE_ALIGN, init_once,
+                                        NULL);
+       if (!bdev_cachep)
+               panic("cannot create bdev slab cache");
+}
+
+/*
+ * Most likely _very_ bad one - but then it's hardly critical for small
+ * /dev and can be fixed when somebody will need really large one.
+ */
+static inline unsigned long hash(dev_t dev)
+{
+       unsigned long tmp = dev;
+       tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2);
+       return tmp & HASH_MASK;
+}
+
+static struct block_device *bdfind(dev_t dev, struct list_head *head)
+{
+       struct list_head *p;
+       struct block_device *bdev;
+       for (p=head->next; p!=head; p=p->next) {
+               bdev = list_entry(p, struct block_device, bd_hash);
+               if (bdev->bd_dev != dev)
+                       continue;
+               atomic_inc(&bdev->bd_count);
+               return bdev;
+       }
+       return NULL;
+}
+
+struct block_device *bdget(dev_t dev)
+{
+       struct list_head * head = bdev_hashtable + hash(dev);
+       struct block_device *bdev, *new_bdev;
+       spin_lock(&bdev_lock);
+       bdev = bdfind(dev, head);
+       spin_unlock(&bdev_lock);
+       if (bdev)
+               return bdev;
+       new_bdev = alloc_bdev();
+       if (!new_bdev)
+               return NULL;
+       atomic_set(&new_bdev->bd_count,1);
+       new_bdev->bd_dev = dev;
+       spin_lock(&bdev_lock);
+       bdev = bdfind(dev, head);
+       if (!bdev) {
+               list_add(&new_bdev->bd_hash, head);
+               spin_unlock(&bdev_lock);
+               return new_bdev;
+       }
+       spin_unlock(&bdev_lock);
+       destroy_bdev(new_bdev);
+       return bdev;
+}
+
+void bdput(struct block_device *bdev)
+{
+       if (atomic_dec_and_test(&bdev->bd_count)) {
+               spin_lock(&bdev_lock);
+               if (atomic_read(&bdev->bd_openers))
+                       BUG();
+               list_del(&bdev->bd_hash);
+               spin_unlock(&bdev_lock);
+               destroy_bdev(bdev);
+       }
+}
+
+static struct {
+       const char *name;
+       struct file_operations *bdops;
+} blkdevs[MAX_BLKDEV] = {
+       { NULL, NULL },
+};
+
+int get_blkdev_list(char * p)
+{
+       int i;
+       int len;
+
+       len = sprintf(p, "\nBlock devices:\n");
+       for (i = 0; i < MAX_BLKDEV ; i++) {
+               if (blkdevs[i].bdops) {
+                       len += sprintf(p+len, "%3d %s\n", i, blkdevs[i].name);
+               }
+       }
+       return len;
+}
+
+/*
+       Return the function table of a device.
+       Load the driver if needed.
+*/
+struct file_operations * get_blkfops(unsigned int major)
+{
+       const struct file_operations *ret = NULL;
+
+       /* major 0 is used for non-device mounts */
+       if (major && major < MAX_BLKDEV) {
+#ifdef CONFIG_KMOD
+               if (!blkdevs[major].bdops) {
+                       char name[20];
+                       sprintf(name, "block-major-%d", major);
+                       request_module(name);
+               }
+#endif
+               ret = blkdevs[major].bdops;
+       }
+       return ret;
+}
+
+int register_blkdev(unsigned int major, const char * name, struct file_operations *bdops)
+{
+       if (major == 0) {
+               for (major = MAX_BLKDEV-1; major > 0; major--) {
+                       if (blkdevs[major].bdops == NULL) {
+                               blkdevs[major].name = name;
+                               blkdevs[major].bdops = bdops;
+                               return major;
+                       }
+               }
+               return -EBUSY;
+       }
+       if (major >= MAX_BLKDEV)
+               return -EINVAL;
+       if (blkdevs[major].bdops && blkdevs[major].bdops != bdops)
+               return -EBUSY;
+       blkdevs[major].name = name;
+       blkdevs[major].bdops = bdops;
+       return 0;
+}
+
+int unregister_blkdev(unsigned int major, const char * name)
+{
+       if (major >= MAX_BLKDEV)
+               return -EINVAL;
+       if (!blkdevs[major].bdops)
+               return -EINVAL;
+       if (strcmp(blkdevs[major].name, name))
+               return -EINVAL;
+       blkdevs[major].name = NULL;
+       blkdevs[major].bdops = NULL;
+       return 0;
+}
+
+/*
+ * This routine checks whether a removable media has been changed,
+ * and invalidates all buffer-cache-entries in that case. This
+ * is a relatively slow routine, so we have to try to minimize using
+ * it. Thus it is called only upon a 'mount' or 'open'. This
+ * is the best way of combining speed and utility, I think.
+ * People changing diskettes in the middle of an operation deserve
+ * to lose :-)
+ */
+int check_disk_change(kdev_t dev)
+{
+       int i;
+       const struct file_operations * bdops;
+       struct super_block * sb;
+
+       i = MAJOR(dev);
+       if (i >= MAX_BLKDEV || (bdops = blkdevs[i].bdops) == NULL)
+               return 0;
+       if (bdops->check_media_change == NULL)
+               return 0;
+       if (!bdops->check_media_change(dev))
+               return 0;
+
+       printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
+               bdevname(dev));
+
+       sb = get_super(dev);
+       if (sb && invalidate_inodes(sb))
+               printk("VFS: busy inodes on changed media.\n");
+
+       invalidate_buffers(dev);
+
+       if (bdops->revalidate)
+               bdops->revalidate(dev);
+       return 1;
+}
+
+int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
+{
+       kdev_t rdev = to_kdev_t(bdev->bd_dev);
+       struct file_operations *fops = get_blkfops(MAJOR(rdev));
+       struct inode inode_fake;
+       int res;
+       mm_segment_t old_fs = get_fs();
+
+       if (!fops || !fops->ioctl)
+               return -EINVAL;
+       inode_fake.i_rdev=rdev;
+       init_waitqueue_head(&inode_fake.i_wait);
+       set_fs(KERNEL_DS);
+       res = fops->ioctl(&inode_fake, NULL, cmd, arg);
+       set_fs(old_fs);
+       return res;
+}
+
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+{
+       int ret = -ENODEV;
+       kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
+       struct file_operations *fops = get_blkfops(MAJOR(rdev));
+       down(&bdev->bd_sem);
+       if (fops) {
+               /*
+                * This crockload is due to bad choice of ->open() type.
+                * It will go away.
+                */
+               struct file fake_file = {};
+               struct dentry fake_dentry = {};
+               struct inode *fake_inode = get_empty_inode();
+               ret = -ENOMEM;
+               if (fake_inode) {
+                       fake_file.f_mode = mode;
+                       fake_file.f_flags = flags;
+                       fake_file.f_dentry = &fake_dentry;
+                       fake_dentry.d_inode = fake_inode;
+                       fake_inode->i_rdev = rdev;
+                       ret = 0;
+                       if (fops->open)
+                               ret = fops->open(fake_inode, &fake_file);
+                       if (!ret)
+                               atomic_inc(&bdev->bd_openers);
+                       iput(fake_inode);
+               }
+       }
+       up(&bdev->bd_sem);
+       return ret;
+}
+
+int blkdev_put(struct block_device *bdev, int kind)
+{
+       int ret = 0;
+       kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
+       struct file_operations *fops = get_blkfops(MAJOR(rdev));
+       down(&bdev->bd_sem);
+       /* syncing will go here */
+       if (atomic_dec_and_test(&bdev->bd_openers)) {
+               /* invalidating buffers will go here */
+       }
+       if (fops->release) {
+               struct inode * fake_inode = get_empty_inode();
+               ret = -ENOMEM;
+               if (fake_inode) {
+                       fake_inode->i_rdev = rdev;
+                       ret = fops->release(fake_inode, NULL);
+                       iput(fake_inode);
+               }
+       }
+       up(&bdev->bd_sem);
+       return ret;
+}
+
+char * bdevname(kdev_t dev)
+{
+       static char buffer[32];
+       const char * name = blkdevs[MAJOR(dev)].name;
+
+       if (!name)
+               name = "unknown-block";
+
+       sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
+       return buffer;
+}
+
+/*
+ * Called every time a block special file is opened
+ */
+int blkdev_open(struct inode * inode, struct file * filp)
+{
+       int ret = -ENODEV;
+       filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
+       if (filp->f_op != NULL){
+               ret = 0;
+               if (filp->f_op->open != NULL)
+                       ret = filp->f_op->open(inode,filp);
+       }       
+       return ret;
+}      
+
+/*
+ * Dummy default file-operations: the only thing this does
+ * is contain the open that then fills in the correct operations
+ * depending on the special file...
+ */
+struct file_operations def_blk_fops = {
+       NULL,           /* lseek */
+       NULL,           /* read */
+       NULL,           /* write */
+       NULL,           /* readdir */
+       NULL,           /* poll */
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       blkdev_open,    /* open */
+       NULL,           /* flush */
+       NULL,           /* release */
+};
+
+struct inode_operations blkdev_inode_operations = {
+       &def_blk_fops,          /* default file operations */
+};
index 4c69112af74a53a5163a7eddb00fa72b29cea5ed..3efb5822a5257c98c33795bab5caf8d627c68026 100644 (file)
@@ -37,9 +37,7 @@ static struct device_struct chrdevs[MAX_CHRDEV] = {
        { NULL, NULL },
 };
 
-static struct device_struct blkdevs[MAX_BLKDEV] = {
-       { NULL, NULL },
-};
+extern int get_blkdev_list(char *);
 
 int get_device_list(char * page)
 {
@@ -52,12 +50,7 @@ int get_device_list(char * page)
                        len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name);
                }
        }
-       len += sprintf(page+len, "\nBlock devices:\n");
-       for (i = 0; i < MAX_BLKDEV ; i++) {
-               if (blkdevs[i].fops) {
-                       len += sprintf(page+len, "%3d %s\n", i, blkdevs[i].name);
-               }
-       }
+       len += get_blkdev_list(page+len);
        return len;
 }
 
@@ -103,16 +96,6 @@ static struct file_operations * get_fops(
        return ret;
 }
 
-
-/*
-       Return the function table of a device.
-       Load the driver if needed.
-*/
-struct file_operations * get_blkfops(unsigned int major)
-{
-       return get_fops (major,0,MAX_BLKDEV,"block-major-%d",blkdevs);
-}
-
 struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
 {
        return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs);
@@ -139,27 +122,6 @@ int register_chrdev(unsigned int major, const char * name, struct file_operation
        return 0;
 }
 
-int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
-{
-       if (major == 0) {
-               for (major = MAX_BLKDEV-1; major > 0; major--) {
-                       if (blkdevs[major].fops == NULL) {
-                               blkdevs[major].name = name;
-                               blkdevs[major].fops = fops;
-                               return major;
-                       }
-               }
-               return -EBUSY;
-       }
-       if (major >= MAX_BLKDEV)
-               return -EINVAL;
-       if (blkdevs[major].fops && blkdevs[major].fops != fops)
-               return -EBUSY;
-       blkdevs[major].name = name;
-       blkdevs[major].fops = fops;
-       return 0;
-}
-
 int unregister_chrdev(unsigned int major, const char * name)
 {
        if (major >= MAX_CHRDEV)
@@ -173,119 +135,6 @@ int unregister_chrdev(unsigned int major, const char * name)
        return 0;
 }
 
-int unregister_blkdev(unsigned int major, const char * name)
-{
-       if (major >= MAX_BLKDEV)
-               return -EINVAL;
-       if (!blkdevs[major].fops)
-               return -EINVAL;
-       if (strcmp(blkdevs[major].name, name))
-               return -EINVAL;
-       blkdevs[major].name = NULL;
-       blkdevs[major].fops = NULL;
-       return 0;
-}
-
-/*
- * This routine checks whether a removable media has been changed,
- * and invalidates all buffer-cache-entries in that case. This
- * is a relatively slow routine, so we have to try to minimize using
- * it. Thus it is called only upon a 'mount' or 'open'. This
- * is the best way of combining speed and utility, I think.
- * People changing diskettes in the middle of an operation deserve
- * to lose :-)
- */
-int check_disk_change(kdev_t dev)
-{
-       int i;
-       struct file_operations * fops;
-       struct super_block * sb;
-
-       i = MAJOR(dev);
-       if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
-               return 0;
-       if (fops->check_media_change == NULL)
-               return 0;
-       if (!fops->check_media_change(dev))
-               return 0;
-
-       printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
-               bdevname(dev));
-
-       sb = get_super(dev);
-       if (sb && invalidate_inodes(sb))
-               printk("VFS: busy inodes on changed media.\n");
-
-       invalidate_buffers(dev);
-
-       if (fops->revalidate)
-               fops->revalidate(dev);
-       return 1;
-}
-
-/*
- * Called every time a block special file is opened
- */
-int blkdev_open(struct inode * inode, struct file * filp)
-{
-       int ret = -ENODEV;
-       filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
-       if (filp->f_op != NULL){
-               ret = 0;
-               if (filp->f_op->open != NULL)
-                       ret = filp->f_op->open(inode,filp);
-       }       
-       return ret;
-}      
-
-int blkdev_release(struct inode * inode)
-{
-       struct file_operations *fops = get_blkfops(MAJOR(inode->i_rdev));
-       if (fops && fops->release)
-               return fops->release(inode,NULL);
-       return 0;
-}
-
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-struct file_operations def_blk_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* poll */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       blkdev_open,    /* open */
-       NULL,           /* flush */
-       NULL,           /* release */
-};
-
-static struct inode_operations blkdev_inode_operations = {
-       &def_blk_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL                    /* revalidate */
-};
-
 /*
  * Called every time a character special file is opened
  */
@@ -307,38 +156,12 @@ int chrdev_open(struct inode * inode, struct file * filp)
  * is contain the open that then fills in the correct operations
  * depending on the special file...
  */
-struct file_operations def_chr_fops = {
-       NULL,           /* lseek */
-       NULL,           /* read */
-       NULL,           /* write */
-       NULL,           /* readdir */
-       NULL,           /* poll */
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       chrdev_open,    /* open */
-       NULL,           /* flush */
-       NULL,           /* release */
+static struct file_operations def_chr_fops = {
+       open:   chrdev_open
 };
 
 static struct inode_operations chrdev_inode_operations = {
-       &def_chr_fops,          /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL                    /* revalidate */
+       &def_chr_fops           /* default file operations */
 };
 
 /*
@@ -352,18 +175,6 @@ char * kdevname(kdev_t dev)
        return buffer;
 }
 
-char * bdevname(kdev_t dev)
-{
-       static char buffer[32];
-       const char * name = blkdevs[MAJOR(dev)].name;
-
-       if (!name)
-               name = "unknown-block";
-
-       sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
-       return buffer;
-}
-
 char * cdevname(kdev_t dev)
 {
        static char buffer[32];
@@ -385,8 +196,9 @@ void init_special_inode(struct inode *inode, umode_t mode, int rdev)
        } else if (S_ISBLK(mode)) {
                inode->i_op = &blkdev_inode_operations;
                inode->i_rdev = to_kdev_t(rdev);
+               inode->i_bdev = bdget(rdev);
        } else if (S_ISFIFO(mode))
-               init_fifo(inode);
+               inode->i_op = &fifo_inode_operations;
        else if (S_ISSOCK(mode))
                ;
        else
index 516e690c9cd325f28b8f046de9c1942b62cd0192..ef4fdadce42de3dd4d9c397c1829e1ec4f6b9d58 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -170,11 +170,3 @@ static struct file_operations def_fifo_fops = {
 struct inode_operations fifo_inode_operations = {
        &def_fifo_fops,         /* default file operations */
 };
-
-
-/* Goner. Filesystems do not use it anymore. */
-
-void init_fifo(struct inode * inode)
-{
-       inode->i_op = &fifo_inode_operations;
-}
index 0dcdf2a87f487db0601a0fa5e079fce90ec2914f..f1a9ebb88d35d1363c45aa9d7aa478f33eb27086 100644 (file)
@@ -257,7 +257,10 @@ void clear_inode(struct inode *inode)
                DQUOT_DROP(inode);
        if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
                inode->i_sb->s_op->clear_inode(inode);
-
+       if (inode->i_bdev) {
+               bdput(inode->i_bdev);
+               inode->i_bdev = NULL;
+       }
        inode->i_state = 0;
 }
 
@@ -472,6 +475,7 @@ static void clean_inode(struct inode *inode)
        inode->i_generation = 0;
        memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
        inode->i_pipe = NULL;
+       inode->i_bdev = NULL;
 }
 
 /*
index d6649bdecdb3344dbfb0863a2c2ae7dd1cee4c7b..d14c18071ed1cf0519d2b971448de3b0e8b71096 100644 (file)
@@ -425,71 +425,54 @@ static int parse_options(char *options, struct iso9660_options * popt)
  */
 #define WE_OBEY_THE_WRITTEN_STANDARDS 1
 
-static unsigned int isofs_get_last_session(kdev_t dev,s32 session )
+static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
 {
-  struct cdrom_multisession ms_info;
-  unsigned int vol_desc_start;
-  struct inode inode_fake;
-  struct file_operations *fops;
-  extern struct file_operations * get_blkfops(unsigned int);
-  int i;
-
-  vol_desc_start=0;
-  fops = get_blkfops(MAJOR(dev));
-  if (fops && fops->ioctl)
-    {
-      /* Whoops.  We must save the old FS, since otherwise
-       * we would destroy the kernels idea about FS on root
-       * mount in read_super... [chexum]
-       */
-      mm_segment_t old_fs=get_fs();
-      inode_fake.i_rdev=dev;
-      init_waitqueue_head(&inode_fake.i_wait);
-      ms_info.addr_format=CDROM_LBA;
-      /* If a minor device was explicitly opened, set session to the
-       * minor number. For instance, if /dev/hdc1 is mounted, session
-       * 1 on the CD-ROM is selected. CD_PART_MAX gives access to
-       * a max of 64 sessions on IDE. SCSI drives must still use
-       * the session option to mount.
-       */
-      if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR))
+       struct cdrom_multisession ms_info;
+       unsigned int vol_desc_start;
+       struct block_device *bdev = sb->s_bdev;
+       kdev_t dev = sb->s_dev;
+       int i;
+
+       vol_desc_start=0;
+       ms_info.addr_format=CDROM_LBA;
+       /* If a minor device was explicitly opened, set session to the
+        * minor number. For instance, if /dev/hdc1 is mounted, session
+        * 1 on the CD-ROM is selected. CD_PART_MAX gives access to
+        * a max of 64 sessions on IDE. SCSI drives must still use
+        * the session option to mount.
+        */
+       if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR))
                session = MINOR(dev) % CD_PART_MAX;
-      set_fs(KERNEL_DS);
-      if(session >= 0 && session <= 99) {
-             struct cdrom_tocentry Te;
-             Te.cdte_track=session;
-             Te.cdte_format=CDROM_LBA;
-             i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
-                                      NULL,
-                                      CDROMREADTOCENTRY,
-                                      (unsigned long) &Te);
-             set_fs(old_fs);
-             if(!i) printk(KERN_ERR"Session %d start %d type %d\n",session,Te.cdte_addr.lba,Te.cdte_ctrl&CDROM_DATA_TRACK);
-             if(i || (Te.cdte_ctrl&CDROM_DATA_TRACK) != 4)
-                       printk(KERN_ERR"Invalid session number or type of track\n");
-               else return Te.cdte_addr.lba;
-      }
-      i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
-                                      NULL,
-                                      CDROMMULTISESSION,
-                                      (unsigned long) &ms_info);
-      set_fs(old_fs);
-      if(session > 0) printk(KERN_ERR"Invalid session number\n");
+       if(session >= 0 && session <= 99) {
+               struct cdrom_tocentry Te;
+               Te.cdte_track=session;
+               Te.cdte_format=CDROM_LBA;
+               i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
+               if (!i) {
+                       printk(KERN_DEBUG "Session %d start %d type %d\n",
+                              session, Te.cdte_addr.lba,
+                              Te.cdte_ctrl&CDROM_DATA_TRACK);
+                       if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
+                               return Te.cdte_addr.lba;
+               }
+                       
+               printk(KERN_ERR "Invalid session number or type of track\n");
+       }
+       i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
+       if(session > 0) printk(KERN_ERR "Invalid session number\n");
 #if 0
-      printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
-      if (i==0)
-       {
-         printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
-         printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
+       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
+       if (i==0) {
+               printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
+               printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
        }
 #endif
-      if (i==0)
+       if (i==0)
 #if WE_OBEY_THE_WRITTEN_STANDARDS
         if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
 #endif
-          vol_desc_start=ms_info.addr.lba;
-    }
-  return vol_desc_start;
+               vol_desc_start=ms_info.addr.lba;
+       return vol_desc_start;
 }
 
 /*
@@ -569,7 +552,7 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
        s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 
        vol_desc_start = (opt.sbsector != -1) ?
-               opt.sbsector : isofs_get_last_session(dev,opt.session);
+               opt.sbsector : isofs_get_last_session(s,opt.session);
 
        for (iso_blknum = vol_desc_start+16;
              iso_blknum < vol_desc_start+100; iso_blknum++)
index bea64227410c2c1cda5a2ee654caf8b44ebfb437..4c67729aa17ba87761c50738859c289c7113ff9b 100644 (file)
@@ -45,7 +45,6 @@
 static DECLARE_MUTEX(mount_sem);
 
 extern void wait_for_keypress(void);
-extern struct file_operations * get_blkfops(unsigned int major);
 
 extern int root_mountflags;
 
@@ -530,7 +529,8 @@ struct super_block *get_empty_super(void)
        return s;
 }
 
-static struct super_block * read_super(kdev_t dev,const char *name,int flags,
+static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
+                                      const char *name, int flags,
                                       void *data, int silent)
 {
        struct super_block * s;
@@ -541,7 +541,7 @@ static struct super_block * read_super(kdev_t dev,const char *name,int flags,
        check_disk_change(dev);
        s = get_super(dev);
        if (s)
-               goto out;
+               goto found;     /* ought to set ->s_bdev */
 
        type = get_fs_type(name);
        if (!type) {
@@ -553,23 +553,30 @@ static struct super_block * read_super(kdev_t dev,const char *name,int flags,
        if (!s)
                goto out;
        s->s_dev = dev;
+       s->s_bdev = bdev;
        s->s_flags = flags;
        s->s_dirt = 0;
        sema_init(&s->s_vfs_rename_sem,1);
        /* N.B. Should lock superblock now ... */
        if (!type->read_super(s, data, silent))
                goto out_fail;
-       s->s_dev = dev; /* N.B. why do this again?? */
        s->s_type = type;
+bd_get:
+       /* tell bdcache that we are going to keep this one */
+       if (bdev)
+               atomic_inc(&bdev->bd_count);
 out:
        return s;
 
-       /* N.B. s_dev should be cleared in type->read_super */
 out_fail:
        s->s_dev = 0;
+       s->s_bdev = 0;
 out_null:
        s = NULL;
        goto out;
+found:
+       s->s_bdev = bdev;
+       goto bd_get;
 }
 
 /*
@@ -632,9 +639,10 @@ static void d_mount(struct dentry *covered, struct dentry *dentry)
        dentry->d_covers = covered;
 }
 
-static int do_umount(kdev_t dev, int unmount_root, int flags)
+static struct block_device *do_umount(kdev_t dev, int unmount_root, int flags)
 {
        struct super_block * sb;
+       struct block_device *bdev;
        int retval;
        
        retval = -ENOENT;
@@ -681,7 +689,7 @@ static int do_umount(kdev_t dev, int unmount_root, int flags)
                retval = 0;
                if (!(sb->s_flags & MS_RDONLY))
                        retval = do_remount_sb(sb, MS_RDONLY, 0);
-               return retval;
+               return ERR_PTR(retval);
        }
 
        retval = d_umount(sb);
@@ -706,43 +714,44 @@ static int do_umount(kdev_t dev, int unmount_root, int flags)
        }
 
        sb->s_dev = 0;          /* Free the superblock */
+       bdev = sb->s_bdev;
+       sb->s_bdev = NULL;
        unlock_super(sb);
 
        remove_vfsmnt(dev);
+
+       return bdev;
+
 out:
-       return retval;
+       return ERR_PTR(retval);
 }
 
 static int umount_dev(kdev_t dev, int flags)
 {
        int retval;
-       struct inode * inode = get_empty_inode();
-
-       retval = -ENOMEM;
-       if (!inode)
-               goto out;
+       struct block_device *bdev;
 
-       inode->i_rdev = dev;
        retval = -ENXIO;
        if (MAJOR(dev) >= MAX_BLKDEV)
-               goto out_iput;
+               goto out;
 
        fsync_dev(dev);
 
        down(&mount_sem);
 
-       retval = do_umount(dev, 0, flags);
-       if (!retval) {
-               fsync_dev(dev);
-               if (dev != ROOT_DEV) {
-                       blkdev_release(inode);
+       bdev = do_umount(dev, 0, flags);
+       if (IS_ERR(bdev))
+               retval = PTR_ERR(bdev);
+       else {
+               retval = 0;
+               if (bdev) {
+                       blkdev_put(bdev, BDEV_FS);
+                       bdput(bdev);
+               } else {
                        put_unnamed_dev(dev);
                }
        }
-
        up(&mount_sem);
-out_iput:
-       iput(inode);
 out:
        return retval;
 }
@@ -751,12 +760,6 @@ out:
  * Now umount can handle mount points as well as block devices.
  * This is important for filesystems which use unnamed block devices.
  *
- * There is a little kludge here with the dummy_inode.  The current
- * vfs release functions only use the r_dev field in the inode so
- * we give them the info they need without using a real inode.
- * If any other fields are ever needed by any block device release
- * functions, they should be faked here.  -- jrs
- *
  * We now support a flag for forced unmount like the other 'big iron'
  * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
  */
@@ -840,14 +843,29 @@ int fs_may_mount(kdev_t dev)
  * Anyone using this new feature must know what he/she is doing.
  */
 
-int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
-            const char * type, int flags, void * data)
+int do_mount(struct block_device *bdev, const char *dev_name,
+            const char *dir_name, const char * type, int flags, void * data)
 {
+       kdev_t dev;
        struct dentry * dir_d;
        struct super_block * sb;
        struct vfsmount *vfsmnt;
        int error;
 
+       if (bdev) {
+               mode_t mode = FMODE_READ; /* we always need it ;-) */
+               if (!(flags & MS_RDONLY))
+                       mode |= FMODE_WRITE;
+               dev = to_kdev_t(bdev->bd_dev);
+               error = blkdev_get(bdev, mode, 0, BDEV_FS);
+               if (error)
+                       return error;
+       } else {
+               dev = get_unnamed_dev();
+               if (!dev)
+                       return -EMFILE; /* huh? */
+       }
+
        error = -EACCES;
        if (!(flags & MS_RDONLY) && dev && is_read_only(dev))
                goto out;
@@ -874,7 +892,7 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
         * read_super just does a get_super().
         */
        error = -EINVAL;
-       sb = read_super(dev, type, flags, data, 0);
+       sb = read_super(dev, bdev, type, flags, data, 0);
        if (!sb)
                goto dput_and_out;
 
@@ -884,20 +902,30 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
         */
        error = -EBUSY;
        if (!fs_may_mount(dev))
-               goto dput_and_out;
+               goto bdput_and_out;
 
        error = -ENOMEM;
        vfsmnt = add_vfsmnt(sb, dev_name, dir_name);
        if (vfsmnt) {
                d_mount(dget(dir_d), sb->s_root);
-               error = 0;
+               dput(dir_d);
+               up(&mount_sem);
+               return 0;
        }
 
+bdput_and_out:
+       sb->s_bdev = NULL;
+       if (bdev)
+               bdput(bdev);
 dput_and_out:
        dput(dir_d);
        up(&mount_sem);
 out:
-       return error;   
+       if (bdev)
+               blkdev_put(bdev, BDEV_FS);
+       else
+               put_unnamed_dev(dev);
+       return error;
 }
 
 
@@ -1017,11 +1045,10 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
        struct file_system_type * fstype;
        struct dentry * dentry = NULL;
        struct inode * inode = NULL;
-       kdev_t dev;
+       struct block_device *bdev = NULL;
        int retval;
        unsigned long flags = 0;
        unsigned long page = 0;
-       struct file dummy;      /* allows read-write or read-only flag */
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1047,7 +1074,6 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
        if (!fstype)            
                goto out;
 
-       memset(&dummy, 0, sizeof(dummy));
        if (fstype->fs_flags & FS_REQUIRES_DEV) {
                dentry = namei(dev_name);
                retval = PTR_ERR(dentry);
@@ -1063,28 +1089,7 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
                if (IS_NODEV(inode))
                        goto dput_and_out;
 
-               dev = inode->i_rdev;
-               retval = -ENXIO;
-               if (MAJOR(dev) >= MAX_BLKDEV)
-                       goto dput_and_out;
-
-               retval = -ENOTBLK;
-               dummy.f_op = get_blkfops(MAJOR(dev));
-               if (!dummy.f_op)
-                       goto dput_and_out;
-
-               if (dummy.f_op->open) {
-                       dummy.f_dentry = dentry;
-                       dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3;
-                       retval = dummy.f_op->open(inode, &dummy);
-                       if (retval)
-                               goto dput_and_out;
-               }
-
-       } else {
-               retval = -EMFILE;
-               if (!(dev = get_unnamed_dev()))
-                       goto out;
+               bdev = inode->i_bdev;
        }
 
        page = 0;
@@ -1092,27 +1097,17 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
                flags = new_flags & ~MS_MGC_MSK;
                retval = copy_mount_options(data, &page);
                if (retval < 0)
-                       goto clean_up;
+                       goto dput_and_out;
        }
-       retval = do_mount(dev, dev_name, dir_name, fstype->name, flags,
+       retval = do_mount(bdev, dev_name, dir_name, fstype->name, flags,
                                (void *) page);
        free_page(page);
-       if (retval)
-               goto clean_up;
 
 dput_and_out:
        dput(dentry);
 out:
        unlock_kernel();
        return retval;
-
-clean_up:
-       if (dummy.f_op) {
-               if (dummy.f_op->release)
-                       dummy.f_op->release(inode, NULL);
-       } else
-               put_unnamed_dev(dev);
-       goto dput_and_out;
 }
 
 void __init mount_root(void)
@@ -1120,8 +1115,8 @@ void __init mount_root(void)
        struct file_system_type * fs_type;
        struct super_block * sb;
        struct vfsmount *vfsmnt;
-       struct inode * d_inode = NULL;
-       struct file filp;
+       struct block_device *bdev = NULL;
+       mode_t mode;
        int retval;
 
 #ifdef CONFIG_ROOT_NFS
@@ -1130,6 +1125,7 @@ void __init mount_root(void)
                if ((fs_type = get_fs_type("nfs"))) {
                        sb = get_empty_super(); /* "can't fail" */
                        sb->s_dev = get_unnamed_dev();
+                       sb->s_bdev = NULL;
                        sb->s_flags = root_mountflags;
                        sema_init(&sb->s_vfs_rename_sem,1);
                        vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
@@ -1177,23 +1173,17 @@ void __init mount_root(void)
        }
 #endif
 
-       memset(&filp, 0, sizeof(filp));
-       d_inode = get_empty_inode();
-       if (!d_inode)
-               panic(__FUNCTION__ ": unable to allocate root inode");
-       d_inode->i_rdev = ROOT_DEV;
-       filp.f_dentry = NULL;
-       if ( root_mountflags & MS_RDONLY)
-               filp.f_mode = 1; /* read only */
-       else
-               filp.f_mode = 3; /* read write */
-       retval = blkdev_open(d_inode, &filp);
+       bdev = bdget(kdev_t_to_nr(ROOT_DEV));
+       if (!bdget)
+               panic(__FUNCTION__ ": unable to allocate root device");
+       mode = FMODE_READ;
+       if (!(root_mountflags & MS_RDONLY))
+               mode |= FMODE_WRITE;
+       retval = blkdev_get(bdev, mode, 0, BDEV_FS);
        if (retval == -EROFS) {
                root_mountflags |= MS_RDONLY;
-               filp.f_mode = 1;
-               retval = blkdev_open(d_inode, &filp);
+               retval = blkdev_get(bdev, FMODE_READ, 0, BDEV_FS);
        }
-       iput(d_inode);
        if (retval)
                /*
                 * Allow the user to distinguish between failed open
@@ -1204,7 +1194,7 @@ void __init mount_root(void)
        else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
                if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
                        continue;
-               sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
+               sb = read_super(ROOT_DEV,bdev,fs_type->name,root_mountflags,NULL,1);
                if (sb) {
                        sb->s_flags = root_mountflags;
                        current->fs->root = dget(sb->s_root);
@@ -1213,8 +1203,10 @@ void __init mount_root(void)
                                fs_type->name,
                                (sb->s_flags & MS_RDONLY) ? " readonly" : "");
                        vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
-                       if (vfsmnt)
+                       if (vfsmnt) {
+                               bdput(bdev); /* sb holds a reference */
                                return;
+                       }
                        panic("VFS: add_vfsmnt failed for root fs");
                }
        }
@@ -1268,16 +1260,20 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
                error = -ENOTDIR;
        }
        if (error) {
-               int umount_error;
+               struct block_device *bdev;
 
                printk(KERN_NOTICE "Trying to unmount old root ... ");
-               umount_error = do_umount(old_root_dev,1, 0);
-               if (!umount_error) {
+               bdev = do_umount(old_root_dev,1, 0);
+               if (!IS_ERR(bdev)) {
                        printk("okay\n");
                        invalidate_buffers(old_root_dev);
+                       if (bdev) {
+                               blkdev_put(bdev, BDEV_FS);
+                               bdput(bdev);
+                       }
                        return 0;
                }
-               printk(KERN_ERR "error %d\n",umount_error);
+               printk(KERN_ERR "error %d\n",PTR_ERR(bdev));
                return error;
        }
        remove_vfsmnt(old_root_dev);
index dc9589609f7f7f2d084acb952810a21915c98616..e2e12df8e6692524add45cea0a954715950ad49f 100644 (file)
@@ -1157,7 +1157,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                }
                case FILE_TYPE_FIFO:
                {
-                       init_special_inode(inode, inode->i_mode|S_FIFO, 0);
+                       init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
                        break;
                }
                case FILE_TYPE_SYMLINK:
index 0f763b5d10c40e1be3a9bee1cd31f989e1a38715..dee98ad71977dec927724cb1044b8ce8daab7edb 100644 (file)
@@ -38,60 +38,36 @@ typedef struct scsi_cmnd   Scsi_Cmnd;
 #include "udf_sb.h"
 
 unsigned int 
-udf_get_last_session(kdev_t dev)
+udf_get_last_session(struct super_block *sb)
 {
        struct cdrom_multisession ms_info;
        unsigned int vol_desc_start;
-       struct inode inode_fake;
-       extern struct file_operations * get_blkfops(unsigned int);
+       struct block_device *bdev = sb->s_bdev;
        int i;
 
        vol_desc_start=0;
-       if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
-       {
-               /* Whoops.  We must save the old FS, since otherwise
-                * we would destroy the kernels idea about FS on root
-                * mount in read_super... [chexum]
-                */
-               mm_segment_t old_fs=get_fs();
-               inode_fake.i_rdev=dev;
-               ms_info.addr_format=CDROM_LBA;
-               set_fs(KERNEL_DS);
-               i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
-                                               NULL,
-                                               CDROMMULTISESSION,
-                                               (unsigned long) &ms_info);
-               set_fs(old_fs);
-
+       ms_info.addr_format=CDROM_LBA;
+       i=ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
 #define WE_OBEY_THE_WRITTEN_STANDARDS 1
-
-               if (i == 0)
-               {
-                       udf_debug("XA disk: %s, vol_desc_start=%d\n",
-                               (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba);
+       if (i == 0) {
+               udf_debug("XA disk: %s, vol_desc_start=%d\n",
+                       (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba);
 #if WE_OBEY_THE_WRITTEN_STANDARDS
-                       if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
+               if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
 #endif
-                               vol_desc_start = ms_info.addr.lba;
-               }
-               else
-               {
-                       udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i);
-               }
-       }
-       else
-       {
-               udf_debug("Device doesn't know how to ioctl?\n");
+                       vol_desc_start = ms_info.addr.lba;
+       } else {
+               udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i);
        }
        return vol_desc_start;
 }
 
 unsigned int
-udf_get_last_block(kdev_t dev, int *flags)
+udf_get_last_block(struct super_block *sb, int *flags)
 {
        extern int *blksize_size[];
-       struct inode inode_fake;
-       extern struct file_operations * get_blkfops(unsigned int);
+       kdev_t dev = sb->s_dev;
+       struct block_device *bdev = sb->s_bdev;
        int ret;
        unsigned long lblock;
        unsigned int hbsize = get_hardblocksize(dev);
@@ -107,44 +83,20 @@ udf_get_last_block(kdev_t dev, int *flags)
        else if (hbsize > secsize)
                div = hbsize / secsize;
 
-       if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
-       {
-      /* Whoops.  We must save the old FS, since otherwise
-       * we would destroy the kernels idea about FS on root
-       * mount in read_super... [chexum]
-       */
-               mm_segment_t old_fs=get_fs();
-               inode_fake.i_rdev=dev;
-               set_fs(KERNEL_DS);
-
-               lblock = 0;
-               ret = get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
-                       NULL,
-                       BLKGETSIZE,
-                       (unsigned long) &lblock);
-
-               if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
-               {
-                       if (mult)
-                               lblock *= mult;
-                       else if (div)
-                               lblock /= div;
-               }
-               else /* CDROM */
-               {
-                       ret = get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
-                               NULL,
-                               CDROM_LAST_WRITTEN,
-                               (unsigned long) &lblock);
-               }
-
-               set_fs(old_fs);
-               if (!ret && lblock)
-                       return lblock - 1;
-       }
-       else
-       {
-               udf_debug("Device doesn't know how to ioctl?\n");
+       lblock = 0;
+       ret = ioctl_by_bdev(bdev, BLKGETSIZE, (unsigned long) &lblock);
+
+       if (!ret && lblock != 0x7FFFFFFF) {
+               /* Hard Disk */
+               if (mult)
+                       lblock *= mult;
+               else if (div)
+                       lblock /= div;
+       } else {
+               /* CDROM */
+               ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
        }
+       if (!ret && lblock)
+               return lblock - 1;
        return 0;
 }
index 31fecbde260251e47d907eea2d3fc12ffe5f3f59..aba702b57f89854e1c3e209a9e13e978e782d2bb 100644 (file)
@@ -1335,14 +1335,14 @@ udf_read_super(struct super_block *sb, void *options, int silent)
                goto error_out;
 
        if ( uopt.session == 0xFFFFFFFF )
-               UDF_SB_SESSION(sb) = udf_get_last_session(sb->s_dev);
+               UDF_SB_SESSION(sb) = udf_get_last_session(sb);
        else
                UDF_SB_SESSION(sb) = uopt.session;
 
        udf_debug("Multi-session=%d\n", UDF_SB_SESSION(sb));
 
        if ( uopt.lastblock == 0xFFFFFFFF )
-               UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb->s_dev, &(UDF_SB(sb)->s_flags));
+               UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb, &(UDF_SB(sb)->s_flags));
        else
                UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
 
index 48dec10c5a70423d1cedf6323eade5a6577cc7cb..f50ca705cce099b86a1a92b46b38cfa4f81dd863 100644 (file)
@@ -158,8 +158,8 @@ extern struct buffer_head *udf_read_untagged(struct super_block *, Uint32, Uint3
 extern void udf_release_data(struct buffer_head *);
 
 /* lowlevel.c */
-extern unsigned int udf_get_last_session(kdev_t);
-extern unsigned int udf_get_last_block(kdev_t, int *);
+extern unsigned int udf_get_last_session(struct super_block *);
+extern unsigned int udf_get_last_block(struct super_block *, int *);
 
 /* partition.c */
 extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
index 3cdb0f6cd5b771ac0e5e7fb967d209368b2ac531..ef4c558daa0ba9a9d35e90ebfdeef6282652b1e1 100644 (file)
@@ -258,9 +258,9 @@ extern inline void init_rwsem(struct rw_semaphore *sem)
 }
 
 /* we use FASTCALL convention for the helpers */
-extern struct rw_semaphore *FASTCALL(down_read_failed(struct rw_semaphore *sem));
-extern struct rw_semaphore *FASTCALL(down_write_failed(struct rw_semaphore *sem));
-extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *sem));
+extern struct rw_semaphore *FASTCALL(__down_read_failed(struct rw_semaphore *sem));
+extern struct rw_semaphore *FASTCALL(__down_write_failed(struct rw_semaphore *sem));
+extern struct rw_semaphore *FASTCALL(__rwsem_wake(struct rw_semaphore *sem));
 
 extern inline void down_read(struct rw_semaphore *sem)
 {
index e77eca26cda353491685950dc414d7672e1df9e7..f2f655150fb46a14a976e613d769791be985c94a 100644 (file)
@@ -174,6 +174,8 @@ extern inline void acpi_dev_idle(struct acpi_dev *dev)
        }
 }
 
+extern int acpi_active;
+
 #else /* CONFIG_ACPI */
 
 extern inline struct acpi_dev*
index b6099060f511a5fbfa31cf6ea4dc271ce7305fd4..8a6b2f1d82cc4dc038ced41fd46ceaad77d5b626 100644 (file)
@@ -340,6 +340,16 @@ struct address_space {
        unsigned long           nrpages;
 };
 
+struct block_device {
+       struct list_head        bd_hash;
+       atomic_t                bd_count;
+/*     struct address_space    bd_data; */
+       dev_t                   bd_dev;  /* not a kdev_t - it's a search key */
+       atomic_t                bd_openers;
+/*     struct bdev_operations *bd_op; */
+       struct semaphore        bd_sem; /* open/close mutex */
+};
+
 struct inode {
        struct list_head        i_hash;
        struct list_head        i_list;
@@ -370,6 +380,7 @@ struct inode {
        spinlock_t              i_shared_lock;
        struct dquot            *i_dquot[MAXQUOTAS];
        struct pipe_inode_info  *i_pipe;
+       struct block_device     *i_bdev;
 
        unsigned long           i_state;
 
@@ -559,6 +570,8 @@ struct super_block {
        struct list_head        s_dirty;        /* dirty inodes */
        struct list_head        s_files;
 
+       struct block_device     *s_bdev;
+
        union {
                struct minix_sb_info    minix_sb;
                struct ext2_sb_info     ext2_sb;
@@ -743,12 +756,17 @@ extern char * getname(const char *);
 #define __getname()    ((char *) __get_free_page(GFP_KERNEL))
 #define putname(name)  free_page((unsigned long)(name))
 
+enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
 extern void kill_fasync(struct fasync_struct *, int, int);
 extern int register_blkdev(unsigned int, const char *, struct file_operations *);
 extern int unregister_blkdev(unsigned int, const char *);
+extern struct block_device *bdget(dev_t);
+extern void bdput(struct block_device *);
 extern int blkdev_open(struct inode *, struct file *);
-extern int blkdev_release (struct inode *);
 extern struct file_operations def_blk_fops;
+extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
+extern int blkdev_get(struct block_device *, mode_t, unsigned, int);
+extern int blkdev_put(struct block_device *, int);
 
 /* fs/devices.c */
 extern int register_chrdev(unsigned int, const char *, struct file_operations *);
@@ -760,8 +778,8 @@ extern char * cdevname(kdev_t);
 extern char * kdevname(kdev_t);
 extern void init_special_inode(struct inode *, umode_t, int);
 
-extern void init_fifo(struct inode *);
 extern struct inode_operations fifo_inode_operations;
+extern struct inode_operations blkdev_inode_operations;
 
 /* Invalid inode operations -- fs/bad_inode.c */
 extern void make_bad_inode(struct inode *);
index 64184285d4549be29db5f6447452bc0b42983300..0c0627782195d91d53a7d864c3f3f6e741dabdfc 100644 (file)
 #include <linux/types.h>
 #include <linux/config.h>
 #include <linux/ioport.h>
+#include <linux/list.h>
 
 #include <asm/pci.h>
 
  * The pci_dev structure is used to describe both PCI and ISAPnP devices.
  */
 struct pci_dev {
-       int active;                     /* device is active */
-       int ro;                         /* Read/Only */
-
+       struct list_head global_list;   /* node in list of all PCI devices */
+       struct list_head bus_list;      /* node in per-bus list */
        struct pci_bus  *bus;           /* bus this device is on */
        struct pci_bus  *subordinate;   /* bus this device bridges to */
-       struct pci_dev  *sibling;       /* next device on this bus */
-       struct pci_dev  *next;          /* chain of all devices */
 
        void            *sysdata;       /* hook for sys-specific extension */
        struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
@@ -332,12 +330,17 @@ struct pci_dev {
 
        char            name[48];       /* Device name */
        char            slot_name[8];   /* Slot name */
+       int active;                     /* device is active */
+       int ro;                         /* Read/Only */
 
        int (*prepare)(struct pci_dev *dev);
        int (*activate)(struct pci_dev *dev);
        int (*deactivate)(struct pci_dev *dev);
 };
 
+#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
+#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
+
 /*
  *  For PCI devices, the region numbers are assigned this way:
  *
@@ -353,16 +356,14 @@ struct pci_dev {
 #define PCI_REGION_FLAG_MASK 0x0f      /* These bits of resource flags tell us the PCI region flags */
 
 struct pci_bus {
+       struct list_head node;          /* node in list of buses */
        struct pci_bus  *parent;        /* parent bus this bridge is on */
-       struct pci_bus  *children;      /* chain of P2P bridges on this bus */
-       struct pci_bus  *next;          /* chain of all PCI buses */
-       struct pci_ops  *ops;           /* configuration access functions */
-
+       struct list_head children;      /* list of child buses */
+       struct list_head devices;       /* list of devices on this bus */
        struct pci_dev  *self;          /* bridge device as seen by parent */
-       struct pci_dev  *devices;       /* devices behind this bridge */
-       struct pci_dev  **last_dev_p;   /* where should next device be linked to */
        struct resource *resource[4];   /* address space routed to this bus */
 
+       struct pci_ops  *ops;           /* configuration access functions */
        void            *sysdata;       /* hook for sys-specific extension */
        struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
 
@@ -381,8 +382,10 @@ struct pci_bus {
        unsigned char   pad1;
 };
 
-extern struct pci_bus  *pci_root;      /* root bus */
-extern struct pci_dev  *pci_devices;   /* list of all devices */
+#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
+
+extern struct list_head pci_root_buses;        /* list of all known PCI buses */
+extern struct list_head pci_devices;   /* list of all devices */
 
 /*
  * Error values that may be returned by PCI functions.
@@ -458,6 +461,7 @@ void pci_name_device(struct pci_dev *dev);
 char *pci_class_name(u32 class);
 void pci_read_bridge_bases(struct pci_bus *child);
 struct resource *pci_find_parent_resource(struct pci_dev *dev, struct resource *res);
+int pci_setup_device(struct pci_dev * dev);
 
 /* Generic PCI functions exported to card drivers */
 
@@ -478,12 +482,16 @@ int pci_write_config_byte(struct pci_dev *dev, int where, u8 val);
 int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
 int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
 
-int pci_setup_device(struct pci_dev * dev);
 int pci_enable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
 int pci_set_power_state(struct pci_dev *dev, int state);
 int pci_assign_resource(struct pci_dev *dev, int i);
 
+#define __pcidev(entry)        list_entry(entry, struct pci_dev, global_list)
+
+#define pci_for_each_dev(dev) \
+       for(dev = __pcidev(pci_devices.next); dev != __pcidev(&pci_devices); dev = __pcidev(dev->global_list.next))
+
 /* Helper functions for low-level code (drivers/pci/setup.c) */
 
 int pci_claim_resource(struct pci_dev *, int);
index b63f406f80602c5492529a2ba14a8543d3b6bbc6..10a7fd810a4f0621d00f41a0eedb93921349d1f2 100644 (file)
@@ -54,6 +54,7 @@ extern void add_blkdev_randomness(int major);
 extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
+extern __u32 secure_ip_id(__u32 daddr);
 extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
                                        __u16 sport, __u16 dport);
 extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
@@ -64,6 +65,10 @@ extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
                                  __u32 daddr, __u16 sport,
                                  __u16 dport, __u32 sseq,
                                  __u32 count, __u32 maxdiff);
+extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
+                                         __u16 sport, __u16 dport);
+
+extern __u32 secure_ipv6_id(__u32 *daddr);
 
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
index ce30d85ef234920edb81cd818de9a0cd60252e13..432741a475a25cbb2b9c165b5ae4b04f2ee8ebdc 100644 (file)
@@ -249,6 +249,11 @@ struct rta_cacheinfo
        __s32   rta_expires;
        __u32   rta_error;
        __u32   rta_used;
+
+#define RTNETLINK_HAVE_PEERINFO 1
+       __u32   rta_id;
+       __u32   rta_ts;
+       __u32   rta_tsage;
 };
 
 /* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
index ab92bbece26f5bebc23d76372002e897557fdcf0..e2f7111350004f0d3daff5b85af5696231af7334 100644 (file)
@@ -245,6 +245,11 @@ enum
        NET_TCP_TW_RECYCLE=66,
        NET_IPV4_ALWAYS_DEFRAG=67,
        NET_IPV4_TCP_KEEPALIVE_INTVL=68,
+       NET_IPV4_INET_PEER_THRESHOLD=69,
+       NET_IPV4_INET_PEER_MINTTL=70,
+       NET_IPV4_INET_PEER_MAXTTL=71,
+       NET_IPV4_INET_PEER_GC_MINTIME=72,
+       NET_IPV4_INET_PEER_GC_MAXTIME=73
 };
 
 enum {
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
new file mode 100644 (file)
index 0000000..3b69aed
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *             INETPEER - A storage for permanent information about peers
+ *
+ *  Version:   $Id: inetpeer.h,v 1.1 2000/01/06 00:41:51 davem Exp $
+ *
+ *  Authors:   Andrey V. Savochkin <saw@msu.ru>
+ */
+
+#ifndef _NET_INETPEER_H
+#define _NET_INETPEER_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+struct inet_peer
+{
+       struct inet_peer        *avl_left, *avl_right;
+       struct inet_peer        *unused_next, **unused_prevp;
+       atomic_t                refcnt;
+       unsigned long           dtime;          /* the time of last use of not
+                                                * referenced entries */
+       __u32                   v4daddr;        /* peer's address */
+       __u16                   avl_height;
+       __u16                   ip_id_count;    /* IP ID for the next packet */
+       __u32                   tcp_ts;
+       unsigned long           tcp_ts_stamp;
+};
+
+void                   inet_initpeers(void) __init;
+
+/* can be called with or without local BH being disabled */
+struct inet_peer       *inet_getpeer(__u32 daddr, int create);
+
+extern spinlock_t inet_peer_unused_lock;
+extern struct inet_peer *inet_peer_unused_head;
+extern struct inet_peer **inet_peer_unused_tailp;
+/* can be called from BH context or outside */
+extern inline void     inet_putpeer(struct inet_peer *p)
+{
+       spin_lock_bh(&inet_peer_unused_lock);
+       if (atomic_dec_and_test(&p->refcnt)) {
+               p->unused_prevp = inet_peer_unused_tailp;
+               p->unused_next = NULL;
+               *inet_peer_unused_tailp = p;
+               inet_peer_unused_tailp = &p->unused_next;
+               p->dtime = jiffies;
+       }
+       spin_unlock_bh(&inet_peer_unused_lock);
+}
+
+extern spinlock_t inet_peer_idlock;
+/* can be called with or without local BH being disabled */
+extern inline __u16    inet_getid(struct inet_peer *p)
+{
+       __u16 id;
+
+       spin_lock_bh(&inet_peer_idlock);
+       id = p->ip_id_count++;
+       spin_unlock_bh(&inet_peer_idlock);
+       return id;
+}
+
+#endif /* _NET_INETPEER_H */
index 419078aba827837455985d25af1a1e467a7126b8..078c958b25eda80e16a8854f1dd6f41faa9c0287 100644 (file)
@@ -96,7 +96,6 @@ extern int            ip_mc_output(struct sk_buff *skb);
 extern int             ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*));
 extern int             ip_do_nat(struct sk_buff *skb);
 extern void            ip_send_check(struct iphdr *ip);
-extern int             ip_id_count;                      
 extern int             ip_queue_xmit(struct sk_buff *skb);
 extern void            ip_init(void);
 extern int             ip_build_xmit(struct sock *sk,
@@ -181,6 +180,16 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
                 !(dst->mxlock&(1<<RTAX_MTU))));
 }
 
+extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst);
+
+extern __inline__ void ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
+{
+       if (iph->frag_off&__constant_htons(IP_DF))
+               iph->id = 0;
+       else
+               __ip_select_ident(iph, dst);
+}
+
 /*
  *     Map a multicast IP onto multicast MAC for type ethernet.
  */
index 3a2e8e2e41a3b81627e956297fd21e110798117c..8bbdcd263d3a0ba4e02bcf89826b8f4082749584 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/config.h>
 #include <net/dst.h>
+#include <net/inetpeer.h>
 #include <linux/in_route.h>
 #include <linux/rtnetlink.h>
 #include <linux/route.h>
@@ -53,6 +54,7 @@ struct rt_key
        __u8                    scope;
 };
 
+struct inet_peer;
 struct rtable
 {
        union
@@ -76,6 +78,7 @@ struct rtable
 
        /* Miscellaneous cached information */
        __u32                   rt_spec_dst; /* RFC1122 specific destination */
+       struct inet_peer        *peer; /* long-living peer info */
 
 #ifdef CONFIG_IP_ROUTE_NAT
        __u32                   rt_src_map;
@@ -138,4 +141,15 @@ extern __inline__ int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32
        return ip_route_output(rp, dst, src, tos, oif);
 }
 
+extern void rt_bind_peer(struct rtable *rt, int create);
+
+extern __inline__ struct inet_peer *rt_get_peer(struct rtable *rt)
+{
+       if (rt->peer)
+               return rt->peer;
+
+       rt_bind_peer(rt, 0);
+       return rt->peer;
+}
+
 #endif /* _ROUTE_H */
index 597214c4b479da1e71863b444a4cd736dd4620fb..0470f031895f74142cc735fac0aeb8d523697081 100644 (file)
@@ -509,6 +509,7 @@ asmlinkage void __init start_kernel(void)
        page_cache_init(mempages);
        kiobuf_init();
        signals_init();
+       bdev_init();
        inode_init();
        file_table_init();
 #if defined(CONFIG_SYSVIPC)
index 8abd4876c9c97ce809c793513f8e5a81d7b4e619..43551c553029027c57a1e494c65b04b284d82237 100644 (file)
@@ -52,8 +52,6 @@
 
 extern int console_loglevel;
 extern void set_device_ro(kdev_t dev,int flag);
-extern struct file_operations * get_blkfops(unsigned int);
-extern int blkdev_release(struct inode * inode);
 #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
 extern int (*do_nfsservctl)(int, void *, void *);
 #endif
@@ -258,9 +256,10 @@ EXPORT_SYMBOL(is_read_only);
 EXPORT_SYMBOL(set_device_ro);
 EXPORT_SYMBOL(bmap);
 EXPORT_SYMBOL(sync_dev);
-EXPORT_SYMBOL(get_blkfops);
 EXPORT_SYMBOL(blkdev_open);
-EXPORT_SYMBOL(blkdev_release);
+EXPORT_SYMBOL(blkdev_get);
+EXPORT_SYMBOL(blkdev_put);
+EXPORT_SYMBOL(ioctl_by_bdev);
 EXPORT_SYMBOL(gendisk_head);
 EXPORT_SYMBOL(resetup_one_dev);
 EXPORT_SYMBOL(unplug_device);
@@ -417,7 +416,6 @@ EXPORT_SYMBOL(clear_inode);
 EXPORT_SYMBOL(nr_async_pages);
 EXPORT_SYMBOL(___strtok);
 EXPORT_SYMBOL(init_special_inode);
-EXPORT_SYMBOL(fifo_inode_operations);
 EXPORT_SYMBOL(read_ahead);
 EXPORT_SYMBOL(get_hash_table);
 EXPORT_SYMBOL(get_empty_inode);
index 5d761bb409a29b10c16a11ac11b62bf7a4b4a166..53a561201319123f9573e05aefd35ec893593538 100644 (file)
@@ -444,7 +444,6 @@ asmlinkage long sys_swapoff(const char * specialfile)
 {
        struct swap_info_struct * p = NULL;
        struct dentry * dentry;
-       struct file filp;
        int i, type, prev;
        int err = -EPERM;
        
@@ -508,17 +507,8 @@ asmlinkage long sys_swapoff(const char * specialfile)
                p->flags = SWP_WRITEOK;
                goto out_dput;
        }
-       if(p->swap_device){
-               memset(&filp, 0, sizeof(filp));         
-               filp.f_dentry = dentry;
-               filp.f_mode = 3; /* read write */
-               /* open it again to get fops */
-               if( !blkdev_open(dentry->d_inode, &filp) &&
-                  filp.f_op && filp.f_op->release){
-                       filp.f_op->release(dentry->d_inode,&filp);
-                       filp.f_op->release(dentry->d_inode,&filp);
-               }
-       }
+       if (p->swap_device)
+               blkdev_put(dentry->d_inode->i_bdev, BDEV_SWAP);
        dput(dentry);
 
        dentry = p->swap_file;
@@ -598,18 +588,17 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
        unsigned int type;
        int i, j, prev;
        int error = -EPERM;
-       struct file filp;
        static int least_priority = 0;
        union swap_header *swap_header = 0;
        int swap_header_version;
        int nr_good_pages = 0;
        unsigned long maxpages;
        int swapfilesize;
+       struct block_device *bdev = NULL;
        
        lock_kernel();
        if (!capable(CAP_SYS_ADMIN))
                goto out;
-       memset(&filp, 0, sizeof(filp));
        p = swap_info;
        for (type = 0 ; type < nr_swapfiles ; type++,p++)
                if (!(p->flags & SWP_USED))
@@ -648,9 +637,9 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
                p->swap_device = dev;
                set_blocksize(dev, PAGE_SIZE);
                
-               filp.f_dentry = swap_dentry;
-               filp.f_mode = 3; /* read write */
-               error = blkdev_open(swap_dentry->d_inode, &filp);
+               bdev = swap_dentry->d_inode->i_bdev;
+
+               error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP);
                if (error)
                        goto bad_swap_2;
                set_blocksize(dev, PAGE_SIZE);
@@ -812,8 +801,8 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
        error = 0;
        goto out;
 bad_swap:
-       if(filp.f_op && filp.f_op->release)
-               filp.f_op->release(filp.f_dentry->d_inode,&filp);
+       if (bdev)
+               blkdev_put(bdev, BDEV_SWAP);
 bad_swap_2:
        if (p->swap_map)
                vfree(p->swap_map);
index a6e0b997c60673166ae162f64f624296bd733269..32e2aca16762f89c6474830af7dfede3603177c4 100644 (file)
@@ -8,7 +8,9 @@ if [ "$CONFIG_IP_ADVANCED_ROUTER" = "y" ]; then
    define_bool CONFIG_NETLINK y
    bool '    IP: policy routing' CONFIG_IP_MULTIPLE_TABLES
    if [ "$CONFIG_IP_MULTIPLE_TABLES" = "y" ]; then
-      bool '      IP: use FWMARK value as routing key' CONFIG_IP_ROUTE_FWMARK
+      if [ "$CONFIG_NETFILTER" = "y" ]; then
+         bool '      IP: use FWMARK value as routing key' CONFIG_IP_ROUTE_FWMARK
+      fi
       bool '      IP: fast network address translation' CONFIG_IP_ROUTE_NAT
    fi
    bool '    IP: equal cost multipath' CONFIG_IP_ROUTE_MULTIPATH
index e2f9a45b7374f7315795fef2b7bb1edaabf0968c..a0d501ec59d4ef4535896b63a8983ab1b7640748 100644 (file)
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := ipv4.o
-IPV4_OBJS := utils.o route.o proc.o protocol.o \
+IPV4_OBJS := utils.o route.o inetpeer.o proc.o protocol.o \
             ip_input.o ip_fragment.o ip_forward.o ip_options.o \
             ip_output.o ip_sockglue.o \
             tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o\
index 749e4eb468c92a565df790f4856e92b0f2a92eaa..93dd763912ed12791154abd09b2472e7a32050c3 100644 (file)
@@ -8,7 +8,7 @@
  *     the older version didn't come out right using gcc 2.5.8, the newer one
  *     seems to fall out with gcc 2.6.2.
  *
- *     Version: $Id: igmp.c,v 1.35 1999/12/15 22:39:10 davem Exp $
+ *     Version: $Id: igmp.c,v 1.36 2000/01/06 00:41:54 davem Exp $
  *
  *     Authors:
  *             Alan Cox <Alan.Cox@linux.org>
@@ -224,13 +224,13 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
        iph->version  = 4;
        iph->ihl      = (sizeof(struct iphdr)+4)>>2;
        iph->tos      = 0;
-       iph->frag_off = 0;
+       iph->frag_off = __constant_htons(IP_DF);
        iph->ttl      = 1;
        iph->daddr    = dst;
        iph->saddr    = rt->rt_src;
        iph->protocol = IPPROTO_IGMP;
        iph->tot_len  = htons(IGMP_SIZE);
-       iph->id       = htons(ip_id_count++);
+       ip_select_ident(iph, &rt->u.dst);
        ((u8*)&iph[1])[0] = IPOPT_RA;
        ((u8*)&iph[1])[1] = 4;
        ((u8*)&iph[1])[2] = 0;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
new file mode 100644 (file)
index 0000000..a20273d
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ *             INETPEER - A storage for permanent information about peers
+ *
+ *  This source is covered by the GNU GPL, the same as all kernel sources.
+ *
+ *  Version:   $Id: inetpeer.c,v 1.1 2000/01/06 00:41:55 davem Exp $
+ *
+ *  Authors:   Andrey V. Savochkin <saw@msu.ru>
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <net/inetpeer.h>
+
+/*
+ *  Theory of operations.
+ *  We keep one entry for each peer IP address.  The nodes contains long-living
+ *  information about the peer which doesn't depend on routes.
+ *  At this moment this information consists only of ID field for the next
+ *  outgoing IP packet.  This field is incremented with each packet as encoded
+ *  in inet_getid() function (include/net/inetpeer.h).
+ *  At the moment of writing this notes identifier of IP packets is generated
+ *  to be unpredictable using this code only for packets subjected
+ *  (actually or potentially) to defragmentation.  I.e. DF packets less than
+ *  PMTU in size uses a constant ID and do not use this code (see
+ *  ip_select_ident() in include/net/ip.h).
+ *
+ *  Route cache entries hold references to our nodes.
+ *  New cache entries get references via lookup by destination IP address in
+ *  the avl tree.  The reference is grabbed only when it's needed i.e. only
+ *  when we try to output IP packet which needs an unpredictable ID (see
+ *  __ip_select_ident() in net/ipv4/route.c).
+ *  Nodes are removed only when reference counter goes to 0.
+ *  When it's happened the node may be removed when a sufficient amount of
+ *  time has been passed since its last use.  The less-recently-used entry can
+ *  also be removed if the pool is overloaded i.e. if the total amount of
+ *  entries is greater-or-equal than the threshold.
+ *
+ *  Node pool is organised as an AVL tree.
+ *  Such an implementation has been chosen not just for fun.  It's a way to
+ *  prevent easy and efficient DoS attacks by creating hash collisions.  A huge
+ *  amount of long living nodes in a single hash slot would significantly delay
+ *  lookups performed with disabled BHs.
+ *
+ *  Serialisation issues.
+ *  1.  Nodes may appear in the tree only with the pool write lock held.
+ *  2.  Nodes may disappear from the tree only with the pool write lock held
+ *      AND reference count being 0.
+ *  3.  Nodes appears and disappears from unused node list only under
+ *      "inet_peer_unused_lock".
+ *  4.  Global variable peer_total is modified under the pool lock.
+ *  5.  struct inet_peer fields modification:
+ *             avl_left, avl_right, avl_parent, avl_height: pool lock
+ *             unused_next, unused_prevp: unused node list lock
+ *             refcnt: atomically against modifications on other CPU;
+ *                usually under some other lock to prevent node disappearing
+ *             dtime: unused node list lock
+ *             v4daddr: unchangeable
+ *             ip_id_count: idlock
+ */
+
+spinlock_t inet_peer_idlock = SPIN_LOCK_UNLOCKED;
+
+static kmem_cache_t *peer_cachep;
+
+#define node_height(x) x->avl_height
+static struct inet_peer peer_fake_node = {
+       avl_left : &peer_fake_node,
+       avl_right : &peer_fake_node,
+       avl_height : 0
+};
+#define peer_avl_empty (&peer_fake_node)
+static struct inet_peer *peer_root = peer_avl_empty;
+static rwlock_t peer_pool_lock = RW_LOCK_UNLOCKED;
+#define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
+
+static volatile int peer_total = 0;
+int inet_peer_threshold = 65536 + 128; /* start to throw entries more
+                                        * aggressively at this stage */
+int inet_peer_minttl = 120 * HZ;       /* TTL under high load: 120 sec */
+int inet_peer_maxttl = 10 * 60 * HZ;   /* usual time to live: 10 min */
+struct inet_peer *inet_peer_unused_head = NULL,
+               **inet_peer_unused_tailp = &inet_peer_unused_head;
+spinlock_t inet_peer_unused_lock = SPIN_LOCK_UNLOCKED;
+#define PEER_MAX_CLEANUP_WORK 30
+
+static void peer_check_expire(unsigned long dummy);
+static struct timer_list peer_periodic_timer =
+       { NULL, NULL, 0, 0, &peer_check_expire };
+int inet_peer_gc_mintime = 10 * HZ,
+    inet_peer_gc_maxtime = 120 * HZ;
+
+
+void __init inet_initpeers(void)
+{
+       struct sysinfo si;
+
+       /* Use the straight interface to information about memory. */
+       si_meminfo(&si);
+       /* The values below were suggested by Alexey Kuznetsov
+        * <kuznet@ms2.inr.ac.ru>.  I don't have any opinion about the values
+        * myself.  --SAW
+        */
+       if (si.totalram <= 32768*1024)
+               inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */
+       if (si.totalram <= 16384*1024)
+               inet_peer_threshold >>= 1; /* about 512KB */
+       if (si.totalram <= 8192*1024)
+               inet_peer_threshold >>= 2; /* about 128KB */
+
+       peer_cachep = kmem_cache_create("inet_peer_cache",
+                       sizeof(struct inet_peer),
+                       0, SLAB_HWCACHE_ALIGN,
+                       NULL, NULL);
+
+       /* All the timers, started at system startup tend
+          to synchronize. Perturb it a bit.
+        */
+       peer_periodic_timer.expires = jiffies
+               + net_random() % inet_peer_gc_maxtime
+               + inet_peer_gc_maxtime;
+       add_timer(&peer_periodic_timer);
+}
+
+/* Called with or without local BH being disabled. */
+static void unlink_from_unused(struct inet_peer *p)
+{
+       spin_lock_bh(&inet_peer_unused_lock);
+       if (p->unused_prevp != NULL) {
+               /* On unused list. */
+               *p->unused_prevp = p->unused_next;
+               if (p->unused_next != NULL)
+                       p->unused_next->unused_prevp = p->unused_prevp;
+               else
+                       inet_peer_unused_tailp = p->unused_prevp;
+               p->unused_prevp = NULL; /* mark it as removed */
+       }
+       spin_unlock_bh(&inet_peer_unused_lock);
+}
+
+/* Called with local BH disabled and the pool lock held. */
+#define lookup(daddr)                                          \
+({                                                             \
+       struct inet_peer *u, **v;                               \
+       stackptr = stack;                                       \
+       *stackptr++ = &peer_root;                               \
+       for (u = peer_root; u != peer_avl_empty; ) {            \
+               if (daddr == u->v4daddr)                        \
+                       break;                                  \
+               if (daddr < u->v4daddr)                         \
+                       v = &u->avl_left;                       \
+               else                                            \
+                       v = &u->avl_right;                      \
+               *stackptr++ = v;                                \
+               u = *v;                                         \
+       }                                                       \
+       u;                                                      \
+})
+
+/* Called with local BH disabled and the pool write lock held. */
+#define lookup_rightempty(start)                               \
+({                                                             \
+       struct inet_peer *u, **v;                               \
+       *stackptr++ = &start->avl_left;                         \
+       v = &start->avl_left;                                   \
+       for (u = *v; u->avl_right != peer_avl_empty; ) {        \
+               v = &u->avl_right;                              \
+               *stackptr++ = v;                                \
+               u = *v;                                         \
+       }                                                       \
+       u;                                                      \
+})
+
+/* Called with local BH disabled and the pool write lock held.
+ * Variable names are the proof of operation correctness.
+ * Look into mm/map_avl.c for more detail description of the ideas.  */
+static void peer_avl_rebalance(struct inet_peer **stack[],
+               struct inet_peer ***stackend)
+{
+       struct inet_peer **nodep, *node, *l, *r;
+       int lh, rh;
+
+       while (stackend > stack) {
+               nodep = *--stackend;
+               node = *nodep;
+               l = node->avl_left;
+               r = node->avl_right;
+               lh = node_height(l);
+               rh = node_height(r);
+               if (lh > rh + 1) { /* l: RH+2 */
+                       struct inet_peer *ll, *lr, *lrl, *lrr;
+                       int lrh;
+                       ll = l->avl_left;
+                       lr = l->avl_right;
+                       lrh = node_height(lr);
+                       if (lrh <= node_height(ll)) {   /* ll: RH+1 */
+                               node->avl_left = lr;    /* lr: RH or RH+1 */
+                               node->avl_right = r;    /* r: RH */
+                               node->avl_height = lrh + 1; /* RH+1 or RH+2 */
+                               l->avl_left = ll;       /* ll: RH+1 */
+                               l->avl_right = node;    /* node: RH+1 or RH+2 */
+                               l->avl_height = node->avl_height + 1;
+                               *nodep = l;
+                       } else { /* ll: RH, lr: RH+1 */
+                               lrl = lr->avl_left;     /* lrl: RH or RH-1 */
+                               lrr = lr->avl_right;    /* lrr: RH or RH-1 */
+                               node->avl_left = lrr;   /* lrr: RH or RH-1 */
+                               node->avl_right = r;    /* r: RH */
+                               node->avl_height = rh + 1; /* node: RH+1 */
+                               l->avl_left = ll;       /* ll: RH */
+                               l->avl_right = lrl;     /* lrl: RH or RH-1 */
+                               l->avl_height = rh + 1; /* l: RH+1 */
+                               lr->avl_left = l;       /* l: RH+1 */
+                               lr->avl_right = node;   /* node: RH+1 */
+                               lr->avl_height = rh + 2;
+                               *nodep = lr;
+                       }
+               } else if (rh > lh + 1) { /* r: LH+2 */
+                       struct inet_peer *rr, *rl, *rlr, *rll;
+                       int rlh;
+                       rr = r->avl_right;
+                       rl = r->avl_left;
+                       rlh = node_height(rl);
+                       if (rlh <= node_height(rr)) {   /* rr: LH+1 */
+                               node->avl_right = rl;   /* rl: LH or LH+1 */
+                               node->avl_left = l;     /* l: LH */
+                               node->avl_height = rlh + 1; /* LH+1 or LH+2 */
+                               r->avl_right = rr;      /* rr: LH+1 */
+                               r->avl_left = node;     /* node: LH+1 or LH+2 */
+                               r->avl_height = node->avl_height + 1;
+                               *nodep = r;
+                       } else { /* rr: RH, rl: RH+1 */
+                               rlr = rl->avl_right;    /* rlr: LH or LH-1 */
+                               rll = rl->avl_left;     /* rll: LH or LH-1 */
+                               node->avl_right = rll;  /* rll: LH or LH-1 */
+                               node->avl_left = l;     /* l: LH */
+                               node->avl_height = lh + 1; /* node: LH+1 */
+                               r->avl_right = rr;      /* rr: LH */
+                               r->avl_left = rlr;      /* rlr: LH or LH-1 */
+                               r->avl_height = lh + 1; /* r: LH+1 */
+                               rl->avl_right = r;      /* r: LH+1 */
+                               rl->avl_left = node;    /* node: LH+1 */
+                               rl->avl_height = lh + 2;
+                               *nodep = rl;
+                       }
+               } else {
+                       node->avl_height = (lh > rh ? lh : rh) + 1;
+               }
+       }
+}
+
+/* Called with local BH disabled and the pool write lock held. */
+#define link_to_pool(n)                                                \
+do {                                                           \
+       n->avl_height = 1;                                      \
+       n->avl_left = peer_avl_empty;                           \
+       n->avl_right = peer_avl_empty;                          \
+       **--stackptr = n;                                       \
+       peer_avl_rebalance(stack, stackptr);                    \
+} while(0)
+
+/* May be called with local BH enabled. */
+static void unlink_from_pool(struct inet_peer *p)
+{
+       int do_free;
+
+       do_free = 0;
+
+       write_lock_bh(&peer_pool_lock);
+       /* Check the reference counter.  It was artificially incremented by 1
+        * in cleanup() function to prevent sudden disappearing.  If the
+        * reference count is still 1 then the node is referenced only as `p'
+        * here and from the pool.  So under the exclusive pool lock it's safe
+        * to remove the node and free it later. */
+       if (atomic_read(&p->refcnt) == 1) {
+               struct inet_peer **stack[PEER_MAXDEPTH];
+               struct inet_peer ***stackptr, ***delp;
+               if (lookup(p->v4daddr) != p)
+                       BUG();
+               delp = stackptr - 1; /* *delp[0] == p */
+               if (p->avl_left == peer_avl_empty) {
+                       *delp[0] = p->avl_right;
+                       --stackptr;
+               } else {
+                       /* look for a node to insert instead of p */
+                       struct inet_peer *t;
+                       t = lookup_rightempty(p);
+                       if (*stackptr[-1] != t)
+                               BUG();
+                       **--stackptr = t->avl_left;
+                       /* t is removed, t->v4daddr > x->v4daddr for any
+                        * x in p->avl_left subtree.
+                        * Put t in the old place of p. */
+                       *delp[0] = t;
+                       t->avl_left = p->avl_left;
+                       t->avl_right = p->avl_right;
+                       t->avl_height = p->avl_height;
+                       if (delp[1] != &p->avl_left)
+                               BUG();
+                       delp[1] = &t->avl_left; /* was &p->avl_left */
+               }
+               peer_avl_rebalance(stack, stackptr);
+               peer_total--;
+               do_free = 1;
+       }
+       write_unlock_bh(&peer_pool_lock);
+
+       if (do_free)
+               kmem_cache_free(peer_cachep, p);
+       else
+               /* The node is used again.  Decrease the reference counter
+                * back.  The loop "cleanup -> unlink_from_unused
+                *   -> unlink_from_pool -> putpeer -> link_to_unused
+                *   -> cleanup (for the same node)"
+                * doesn't really exist because the entry will have a
+                * recent deletion time and will not be cleaned again soon. */
+               inet_putpeer(p);
+}
+
+/* May be called with local BH enabled. */
+static int cleanup_once(unsigned long ttl)
+{
+       struct inet_peer *p;
+
+       /* Remove the first entry from the list of unused nodes. */
+       spin_lock_bh(&inet_peer_unused_lock);
+       p = inet_peer_unused_head;
+       if (p != NULL) {
+               if (time_after(p->dtime + ttl, jiffies)) {
+                       /* Do not prune fresh entries. */
+                       spin_unlock_bh(&inet_peer_unused_lock);
+                       return -1;
+               }
+               inet_peer_unused_head = p->unused_next;
+               if (p->unused_next != NULL)
+                       p->unused_next->unused_prevp = p->unused_prevp;
+               else
+                       inet_peer_unused_tailp = p->unused_prevp;
+               p->unused_prevp = NULL; /* mark as not on the list */
+               /* Grab an extra reference to prevent node disappearing
+                * before unlink_from_pool() call. */
+               atomic_inc(&p->refcnt);
+       }
+       spin_unlock_bh(&inet_peer_unused_lock);
+
+       if (p == NULL)
+               /* It means that the total number of USED entries has
+                * grown over inet_peer_threshold.  It shouldn't really
+                * happen because of entry limits in route cache. */
+               return -1;
+
+       unlink_from_pool(p);
+       return 0;
+}
+
+/* Called with or without local BH being disabled. */
+struct inet_peer *inet_getpeer(__u32 daddr, int create)
+{
+       struct inet_peer *p, *n;
+       struct inet_peer **stack[PEER_MAXDEPTH], ***stackptr;
+
+       /* Look up for the address quickly. */
+       read_lock_bh(&peer_pool_lock);
+       p = lookup(daddr);
+       if (p != peer_avl_empty)
+               atomic_inc(&p->refcnt);
+       read_unlock_bh(&peer_pool_lock);
+
+       if (p != peer_avl_empty) {
+               /* The existing node has been found. */
+               /* Remove the entry from unused list if it was there. */
+               unlink_from_unused(p);
+               return p;
+       }
+
+       if (!create)
+               return NULL;
+
+       /* Allocate the space outside the locked region. */
+       n = kmem_cache_alloc(peer_cachep, GFP_ATOMIC);
+       if (n == NULL)
+               return NULL;
+       n->v4daddr = daddr;
+       atomic_set(&n->refcnt, 1);
+       n->ip_id_count = secure_ip_id(daddr);
+       n->tcp_ts_stamp = 0;
+
+       write_lock_bh(&peer_pool_lock);
+       /* Check if an entry has suddenly appeared. */
+       p = lookup(daddr);
+       if (p != peer_avl_empty)
+               goto out_free;
+
+       /* Link the node. */
+       link_to_pool(n);
+       n->unused_prevp = NULL; /* not on the list */
+       peer_total++;
+       write_unlock_bh(&peer_pool_lock);
+
+       if (peer_total >= inet_peer_threshold)
+               /* Remove one less-recently-used entry. */
+               cleanup_once(0);
+
+       return n;
+
+out_free:
+       /* The appropriate node is already in the pool. */
+       atomic_inc(&p->refcnt);
+       write_unlock_bh(&peer_pool_lock);
+       /* Remove the entry from unused list if it was there. */
+       unlink_from_unused(p);
+       /* Free preallocated the preallocated node. */
+       kmem_cache_free(peer_cachep, n);
+       return p;
+}
+
+/* Called with local BH disabled. */
+static void peer_check_expire(unsigned long dummy)
+{
+       int i;
+       int ttl;
+
+       if (peer_total >= inet_peer_threshold)
+               ttl = inet_peer_minttl;
+       else
+               ttl = inet_peer_maxttl
+                               - (inet_peer_maxttl - inet_peer_minttl) / HZ *
+                                       peer_total / inet_peer_threshold * HZ;
+       for (i = 0; i < PEER_MAX_CLEANUP_WORK && !cleanup_once(ttl); i++);
+
+       /* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
+        * interval depending on the total number of entries (more entries,
+        * less interval). */
+       peer_periodic_timer.expires = jiffies
+               + inet_peer_gc_maxtime
+               - (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
+                       peer_total / inet_peer_threshold * HZ;
+       add_timer(&peer_periodic_timer);
+}
index 0a54020301d831e83ed9f066c1397af3dece044a..b00584e5927d39809e048d62daf9c3af317a4107 100644 (file)
@@ -815,7 +815,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        iph->tot_len            =       htons(skb->len);
-       iph->id                 =       htons(ip_id_count++);
+       ip_select_ident(iph, &rt->u.dst);
        ip_send_check(iph);
 
        stats->tx_bytes += skb->len;
index 12749c4b10f99dc6387e36c2abed67fb7adc3b70..f89109f15f03445788ed150b7bca5cc39d6ed266 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) output module.
  *
- * Version:    $Id: ip_output.c,v 1.75 1999/12/21 04:05:04 davem Exp $
+ * Version:    $Id: ip_output.c,v 1.76 2000/01/06 00:41:57 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -71,6 +71,7 @@
 #include <net/icmp.h>
 #include <net/raw.h>
 #include <net/checksum.h>
+#include <net/inetpeer.h>
 #include <linux/igmp.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/mroute.h>
@@ -82,8 +83,6 @@
 
 int sysctl_ip_dynaddr = 0;
 
-int ip_id_count = 0;
-
 /* Generate a checksum for an outgoing IP datagram. */
 __inline__ void ip_send_check(struct iphdr *iph)
 {
@@ -154,7 +153,7 @@ void ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
 {
        struct rtable *rt = (struct rtable *)skb->dst;
        struct iphdr *iph;
-       
+
        /* Build the IP header. */
        if (opt)
                iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr) + opt->optlen);
@@ -172,7 +171,7 @@ void ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
        iph->saddr    = rt->rt_src;
        iph->protocol = sk->protocol;
        iph->tot_len  = htons(skb->len);
-       iph->id       = htons(ip_id_count++);
+       ip_select_ident(iph, &rt->u.dst);
        skb->nh.iph   = iph;
 
        if (opt && opt->optlen) {
@@ -356,6 +355,8 @@ static inline int ip_queue_xmit2(struct sk_buff *skb)
        if (ip_dont_fragment(sk, &rt->u.dst))
                iph->frag_off |= __constant_htons(IP_DF);
 
+       ip_select_ident(iph, &rt->u.dst);
+
        /* Add an IP checksum. */
        ip_send_check(iph);
 
@@ -375,6 +376,7 @@ fragment:
                kfree_skb(skb);
                return -EMSGSIZE;
        }
+       ip_select_ident(iph, &rt->u.dst);
        return ip_fragment(skb, skb->dst->output);
 }
 
@@ -429,7 +431,6 @@ int ip_queue_xmit(struct sk_buff *skb)
        }
 
        iph->tot_len = htons(skb->len);
-       iph->id = htons(ip_id_count++);
 
        return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
                       ip_queue_xmit2);
@@ -475,7 +476,7 @@ static int ip_build_xmit_slow(struct sock *sk,
        int err;
        int offset, mf;
        int mtu;
-       unsigned short id;
+       u16 id = 0;
 
        int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
        int nfrags=0;
@@ -485,7 +486,7 @@ static int ip_build_xmit_slow(struct sock *sk,
        mtu = rt->u.dst.pmtu;
        if (ip_dont_fragment(sk, &rt->u.dst))
                df = htons(IP_DF);
-  
+
        length -= sizeof(struct iphdr);
 
        if (opt) {
@@ -493,12 +494,12 @@ static int ip_build_xmit_slow(struct sock *sk,
                maxfraglen = ((mtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
        } else {
                fragheaderlen = sizeof(struct iphdr);
-               
+
                /*
                 *      Fragheaderlen is the size of 'overhead' on each buffer. Now work
                 *      out the size of the frames to send.
                 */
-        
+
                maxfraglen = ((mtu-sizeof(struct iphdr)) & ~7) + fragheaderlen;
        }
 
@@ -510,15 +511,15 @@ static int ip_build_xmit_slow(struct sock *sk,
        /*
         *      Start at the end of the frame by handling the remainder.
         */
-        
+
        offset = length - (length % (maxfraglen - fragheaderlen));
-       
+
        /*
         *      Amount of memory to allocate for final fragment.
         */
-        
+
        fraglen = length - offset + fragheaderlen;
-       
+
        if (length-offset==0) {
                fraglen = maxfraglen;
                offset -= maxfraglen-fragheaderlen;
@@ -527,30 +528,24 @@ static int ip_build_xmit_slow(struct sock *sk,
        /*
         *      The last fragment will not have MF (more fragments) set.
         */
-        
+
        mf = 0;
 
        /*
         *      Don't fragment packets for path mtu discovery.
         */
-        
-       if (offset > 0 && df) { 
+
+       if (offset > 0 && sk->protinfo.af_inet.pmtudisc==IP_PMTUDISC_DO) { 
                ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu);
                return -EMSGSIZE;
        }
        if (flags&MSG_PROBE)
                goto out;
 
-       /*
-        *      Get an identifier
-        */
-        
-       id = htons(ip_id_count++);
-
        /*
         *      Begin outputting the bytes.
         */
-        
+
        do {
                char *data;
                struct sk_buff * skb;
@@ -566,7 +561,7 @@ static int ip_build_xmit_slow(struct sock *sk,
                /*
                 *      Fill in the control structures
                 */
-                
+
                skb->priority = sk->priority;
                skb->dst = dst_clone(&rt->u.dst);
                skb_reserve(skb, hh_len);
@@ -574,14 +569,14 @@ static int ip_build_xmit_slow(struct sock *sk,
                /*
                 *      Find where to start putting bytes.
                 */
-                
+
                data = skb_put(skb, fraglen);
                skb->nh.iph = (struct iphdr *)data;
 
                /*
                 *      Only write IP header onto non-raw packets 
                 */
-                
+
                {
                        struct iphdr *iph = (struct iphdr *)data;
 
@@ -594,9 +589,23 @@ static int ip_build_xmit_slow(struct sock *sk,
                        }
                        iph->tos = sk->protinfo.af_inet.tos;
                        iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4);
+                       iph->frag_off = htons(offset>>3)|mf|df;
                        iph->id = id;
-                       iph->frag_off = htons(offset>>3);
-                       iph->frag_off |= mf|df;
+                       if (!mf) {
+                               if (offset || !df) {
+                                       /* Select an unpredictable ident only
+                                        * for packets without DF or having
+                                        * been fragmented.
+                                        */
+                                       __ip_select_ident(iph, &rt->u.dst);
+                                       id = iph->id;
+                               }
+
+                               /*
+                                *      Any further fragments will have MF set.
+                                */
+                               mf = htons(IP_MF);
+                       }
                        if (rt->rt_type == RTN_MULTICAST)
                                iph->ttl = sk->protinfo.af_inet.mc_ttl;
                        else
@@ -607,14 +616,8 @@ static int ip_build_xmit_slow(struct sock *sk,
                        iph->daddr = rt->rt_dst;
                        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
                        data += iph->ihl*4;
-                       
-                       /*
-                        *      Any further fragments will have MF set.
-                        */
-                        
-                       mf = htons(IP_MF);
                }
-               
+
                /*
                 *      User data callback
                 */
@@ -712,20 +715,20 @@ int ip_build_xmit(struct sock *sk,
                goto error; 
        skb_reserve(skb, hh_len);
        }
-       
+
        skb->priority = sk->priority;
        skb->dst = dst_clone(&rt->u.dst);
 
        skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length);
-       
+
        if(!sk->protinfo.af_inet.hdrincl) {
                iph->version=4;
                iph->ihl=5;
                iph->tos=sk->protinfo.af_inet.tos;
                iph->tot_len = htons(length);
-               iph->id=htons(ip_id_count++);
                iph->frag_off = df;
                iph->ttl=sk->protinfo.af_inet.mc_ttl;
+               ip_select_ident(iph, &rt->u.dst);
                if (rt->rt_type != RTN_MULTICAST)
                        iph->ttl=sk->protinfo.af_inet.ttl;
                iph->protocol=sk->protocol;
@@ -757,8 +760,6 @@ error:
        ip_statistics.IpOutDiscards++;
        return err; 
 }
-                      
-
 
 /*
  *     This IP datagram is too large to be sent in one piece.  Break it up into
@@ -905,7 +906,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
        kfree_skb(skb);
        ip_statistics.IpFragOKs++;
        return err;
-       
+
 fail:
        kfree_skb(skb); 
        ip_statistics.IpFragFails++;
@@ -1006,7 +1007,6 @@ static struct packet_type ip_packet_type =
        NULL,
 };
 
-
 /*
  *     IP registers the packet type and then calls the subprotocol initialisers
  */
@@ -1016,9 +1016,9 @@ void __init ip_init(void)
        dev_add_pack(&ip_packet_type);
 
        ip_rt_init();
+       inet_initpeers();
 
 #ifdef CONFIG_IP_MULTICAST
        proc_net_create("igmp", 0, ip_mc_procinfo);
 #endif
 }
-
index 0a5ae3cfe20e73e91de949fbfc383f6f49842b82..5518ec1cb28365b9a5539f3ed95bc4e37e915542 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Linux NET3:     IP/IP protocol decoder. 
  *
- *     Version: $Id: ipip.c,v 1.29 1999/08/31 07:03:42 davem Exp $
+ *     Version: $Id: ipip.c,v 1.30 2000/01/06 00:41:55 davem Exp $
  *
  *     Authors:
  *             Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
@@ -616,7 +616,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
                iph->ttl        =       old_iph->ttl;
 
        iph->tot_len            =       htons(skb->len);
-       iph->id                 =       htons(ip_id_count++);
+       ip_select_ident(iph, &rt->u.dst);
        ip_send_check(iph);
 
        stats->tx_bytes += skb->len;
index 4c1ac3c9483c319cc3dd3b51ae8033eea0642a67..cba4995cc5664e9acac25ac08c055e8b4f3d5363 100644 (file)
@@ -9,7 +9,7 @@
  *     as published by the Free Software Foundation; either version
  *     2 of the License, or (at your option) any later version.
  *
- *     Version: $Id: ipmr.c,v 1.48 1999/12/15 22:39:16 davem Exp $
+ *     Version: $Id: ipmr.c,v 1.49 2000/01/06 00:41:56 davem Exp $
  *
  *     Fixes:
  *     Michael Chastain        :       Incorrect size of copying.
@@ -1095,7 +1095,7 @@ static void ip_encap(struct sk_buff *skb, u32 saddr, u32 daddr)
        iph->protocol   =       IPPROTO_IPIP;
        iph->ihl        =       5;
        iph->tot_len    =       htons(skb->len);
-       iph->id         =       htons(ip_id_count++);
+       ip_select_ident(iph, skb->dst);
        ip_send_check(iph);
 
        skb->h.ipiph = skb->nh.iph;
index 20a41f13f2ddad17bc9765444e284cab5fb6d1a7..78e1455c1bec51b255ca7e910ab382a6fe074281 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             RAW - implementation of IP "raw" sockets.
  *
- * Version:    $Id: raw.c,v 1.44 1999/12/15 22:39:21 davem Exp $
+ * Version:    $Id: raw.c,v 1.45 2000/01/06 00:41:58 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -257,6 +257,7 @@ struct rawfakehdr
 {
        struct  iovec *iov;
        u32     saddr;
+       struct dst_entry *dst;
 };
 
 /*
@@ -296,7 +297,7 @@ static int raw_getrawfrag(const void *p, char *to, unsigned int offset, unsigned
                 *      ip_build_xmit clean (well less messy).
                 */
                if (!iph->id)
-                       iph->id = htons(ip_id_count++);
+                       ip_select_ident(iph, rfh->dst);
                iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
        }
        return 0;
@@ -416,6 +417,7 @@ back_from_confirm:
 
        rfh.iov = msg->msg_iov;
        rfh.saddr = rt->rt_src;
+       rfh.dst = &rt->u.dst;
        if (!ipc.addr)
                ipc.addr = rt->rt_dst;
        err=ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag : raw_getfrag,
index b16f5eb1e31d101a8788e46af796525054d22ac5..3d000201b5633752e2ffa242189b5bd38bd948bd 100644 (file)
 #include <linux/pkt_sched.h>
 #include <linux/mroute.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/random.h>
 #include <net/protocol.h>
 #include <net/ip.h>
 #include <net/route.h>
+#include <net/inetpeer.h>
 #include <net/sock.h>
 #include <net/ip_fib.h>
 #include <net/arp.h>
@@ -134,6 +136,7 @@ static struct timer_list rt_periodic_timer =
 static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32);
 static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
                                           struct sk_buff *);
+static void              ipv4_dst_destroy(struct dst_entry * dst);
 static struct dst_entry * ipv4_negative_advice(struct dst_entry *);
 static void              ipv4_link_failure(struct sk_buff *skb);
 static int rt_garbage_collect(void);
@@ -148,7 +151,7 @@ struct dst_ops ipv4_dst_ops =
        rt_garbage_collect,
        ipv4_dst_check,
        ipv4_dst_reroute,
-       NULL,
+       ipv4_dst_destroy,
        ipv4_negative_advice,
        ipv4_link_failure,
        sizeof(struct rtable),
@@ -626,6 +629,65 @@ restart:
        return 0;
 }
 
+void rt_bind_peer(struct rtable *rt, int create)
+{
+       static spinlock_t rt_peer_lock = SPIN_LOCK_UNLOCKED;
+       struct inet_peer *peer;
+
+       peer = inet_getpeer(rt->rt_dst, create);
+
+       spin_lock_bh(&rt_peer_lock);
+       if (rt->peer == NULL) {
+               rt->peer = peer;
+               peer = NULL;
+       }
+       spin_unlock_bh(&rt_peer_lock);
+       if (peer)
+               inet_putpeer(peer);
+}
+
+/*
+ * Peer allocation may fail only in serious out-of-memory conditions.  However
+ * we still can generate some output.
+ * Random ID selection looks a bit dangerous because we have no chances to
+ * select ID being unique in a reasonable period of time.
+ * But broken packet identifier may be better than no packet at all.
+ */
+static void ip_select_fb_ident(struct iphdr *iph)
+{
+       static spinlock_t ip_fb_id_lock = SPIN_LOCK_UNLOCKED;
+       static u32 ip_fallback_id;
+       u32 salt;
+
+       spin_lock_bh(&ip_fb_id_lock);
+       salt = secure_ip_id(ip_fallback_id ^ iph->daddr);
+       iph->id = salt & 0xFFFF;
+       ip_fallback_id = salt;
+       spin_unlock_bh(&ip_fb_id_lock);
+}
+
+void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
+{
+       struct rtable *rt = (struct rtable *) dst;
+
+       if (rt) {
+               if (rt->peer == NULL)
+                       rt_bind_peer(rt, 1);
+
+               /* If peer is attached to destination, it is never detached,
+                  so that we need not to grab a lock to dereference it.
+                */
+               if (rt->peer) {
+                       iph->id = inet_getid(rt->peer);
+                       return;
+               }
+       } else {
+               printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", NET_CALLER(iph));
+       }
+
+       ip_select_fb_ident(iph);
+}
+
 static void rt_del(unsigned hash, struct rtable *rt)
 {
        struct rtable **rthp;
@@ -727,6 +789,9 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
                                /* Redirect received -> path was valid */
                                dst_confirm(&rth->u.dst);
 
+                               if (rt->peer)
+                                       atomic_inc(&rt->peer->refcnt);
+
                                if (!arp_bind_neighbour(&rt->u.dst) ||
                                    !(rt->u.dst.neighbour->nud_state&NUD_VALID)) {
                                        if (rt->u.dst.neighbour)
@@ -973,6 +1038,17 @@ static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
        return NULL;
 }
 
+static void ipv4_dst_destroy(struct dst_entry * dst)
+{
+       struct rtable *rt = (struct rtable *) dst;
+       struct inet_peer *peer = rt->peer;
+
+       if (peer) {
+               rt->peer = NULL;
+               inet_putpeer(peer);
+       }
+}
+
 static void ipv4_link_failure(struct sk_buff *skb)
 {
        struct rtable *rt;
@@ -1885,6 +1961,16 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int no
        else
                ci.rta_expires = 0;
        ci.rta_error = rt->u.dst.error;
+       ci.rta_id = 0;
+       ci.rta_ts = 0;
+       ci.rta_tsage = 0;
+       if (rt->peer) {
+               ci.rta_id = rt->peer->ip_id_count;
+               if (rt->peer->tcp_ts_stamp) {
+                       ci.rta_ts = rt->peer->tcp_ts;
+                       ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
+               }
+       }
 #ifdef CONFIG_IP_MROUTE
        eptr = (struct rtattr*)skb->tail;
 #endif
index 1ff1566af21e6a987b5ae95e380b60dd0a589e09..1557974c58230a249ab7e203687e63c718a03876 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.40 1999/09/07 02:31:17 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.41 2000/01/06 00:42:03 davem Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -70,6 +70,13 @@ extern int sysctl_icmp_echoreply_time;
 /* From igmp.c */
 extern int sysctl_igmp_max_memberships;
 
+/* From inetpeer.c */
+extern int inet_peer_threshold;
+extern int inet_peer_minttl;
+extern int inet_peer_maxttl;
+extern int inet_peer_gc_mintime;
+extern int inet_peer_gc_maxtime;
+
 int tcp_retr1_max = 255; 
 
 struct ipv4_config ipv4_config;
@@ -200,6 +207,20 @@ ctl_table ipv4_table[] = {
        {NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships",
         &sysctl_igmp_max_memberships, sizeof(int), 0644, NULL, &proc_dointvec},
 #endif
+       {NET_IPV4_INET_PEER_THRESHOLD, "inet_peer_threshold",
+        &inet_peer_threshold, sizeof(int), 0644, NULL, &proc_dointvec},
+       {NET_IPV4_INET_PEER_MINTTL, "inet_peer_minttl",
+        &inet_peer_minttl, sizeof(int), 0644, NULL,
+        &proc_dointvec_jiffies, &sysctl_jiffies},
+       {NET_IPV4_INET_PEER_MAXTTL, "inet_peer_maxttl",
+        &inet_peer_maxttl, sizeof(int), 0644, NULL,
+        &proc_dointvec_jiffies, &sysctl_jiffies},
+       {NET_IPV4_INET_PEER_GC_MINTIME, "inet_peer_gc_mintime",
+        &inet_peer_gc_mintime, sizeof(int), 0644, NULL,
+        &proc_dointvec_jiffies, &sysctl_jiffies},
+       {NET_IPV4_INET_PEER_GC_MAXTIME, "inet_peer_gc_maxtime",
+        &inet_peer_gc_maxtime, sizeof(int), 0644, NULL,
+        &proc_dointvec_jiffies, &sysctl_jiffies},
        {0}
 };
 
index 70667548cad9e8ba2fbadf4c170865e1c71a97e2..e1b6d70ab400401749f931bf9b04bdf80edd85e8 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.192 1999/12/23 02:04:50 davem Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.193 2000/01/06 00:42:01 davem Exp $
  *
  *             IPv4 specific functions
  *
@@ -595,7 +595,8 @@ __inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport
 
 static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
 {
-       return secure_tcp_sequence_number(sk->saddr, sk->daddr,
+       return secure_tcp_sequence_number(skb->nh.iph->daddr,
+                                         skb->nh.iph->saddr,
                                          skb->h.th->dest,
                                          skb->h.th->source);
 }
index bfeff3dc9d2f4bbbdf64775a1367f475528db297..2f1d8800e9b26e15b6e254fee593fd74050adc0a 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: ip6_output.c,v 1.22 1999/08/20 11:06:21 davem Exp $
+ *     $Id: ip6_output.c,v 1.23 2000/01/06 00:42:07 davem Exp $
  *
  *     Based on linux/net/ipv4/ip_output.c
  *
 #include <net/rawv6.h>
 #include <net/icmp.h>
 
-static u32     ipv6_fragmentation_id = 1;
+static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
+{
+       static u32 ipv6_fragmentation_id = 1;
+       static spinlock_t ip6_id_lock = SPIN_LOCK_UNLOCKED;
+
+       spin_lock_bh(&ip6_id_lock);
+       fhdr->identification = ipv6_fragmentation_id;
+       if (++ipv6_fragmentation_id == 0)
+               ipv6_fragmentation_id = 1;
+       spin_unlock_bh(&ip6_id_lock);
+}
 
 int ip6_output(struct sk_buff *skb)
 {
@@ -224,7 +234,7 @@ static __inline__ u8 * ipv6_build_fraghdr(struct sk_buff *skb, u8* prev_hdr, uns
 
        fhdr->reserved = 0;
        fhdr->frag_off = htons(offset);
-       fhdr->identification = ipv6_fragmentation_id++;
+       ipv6_select_ident(skb, fhdr);
        return &fhdr->nexthdr;
 }
 
index 6e6235fb42e219652aa6160586797d794422e5bc..b39959f4f18b0bfc1827a15de68543e70603df77 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: route.c,v 1.42 1999/12/15 22:39:53 davem Exp $
+ *     $Id: route.c,v 1.43 2000/01/06 00:42:08 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1544,6 +1544,9 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
        ci.rta_used = rt->u.dst.__use;
        ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
        ci.rta_error = rt->u.dst.error;
+       ci.rta_id = 0;
+       ci.rta_ts = 0;
+       ci.rta_tsage = 0;
        RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
        nlh->nlmsg_len = skb->tail - b;
        return skb->len;
index 8691d5de79a2f853e3c70dad3e35363d549b15e2..818ad66caa0c338eff4d36d473461d31a6c0e774 100644 (file)
@@ -6,7 +6,7 @@
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *     Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
  *
- *     $Id: sit.c,v 1.34 1999/08/31 07:04:16 davem Exp $
+ *     $Id: sit.c,v 1.35 2000/01/06 00:42:08 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -544,7 +544,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
                iph->ttl        =       iph6->hop_limit;
 
        iph->tot_len            =       htons(skb->len);
-       iph->id                 =       htons(ip_id_count++);
+       ip_select_ident(iph, &rt->u.dst);
        ip_send_check(iph);
 
        stats->tx_bytes += skb->len;
index 9ae22d8181b2096b8acf97cf5165bfee672c140c..6e71f54797346d34da8000c1750d14c1fd40025d 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: tcp_ipv6.c,v 1.114 2000/01/03 17:19:17 davem Exp $
+ *     $Id: tcp_ipv6.c,v 1.115 2000/01/06 00:42:09 davem Exp $
  *
  *     Based on: 
  *     linux/net/ipv4/tcp.c
@@ -343,20 +343,17 @@ static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
 
 static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
 {
-       __u32 si;
-       __u32 di;
-
        if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
-               si = skb->nh.ipv6h->saddr.s6_addr32[3];
-               di = skb->nh.ipv6h->daddr.s6_addr32[3];
+               return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
+                                                   skb->nh.ipv6h->saddr.s6_addr32,
+                                                   skb->h.th->dest,
+                                                   skb->h.th->source);
        } else {
-               si = skb->nh.iph->saddr;
-               di = skb->nh.iph->daddr;
+               return secure_tcp_sequence_number(skb->nh.iph->daddr,
+                                                 skb->nh.iph->saddr,
+                                                 skb->h.th->dest,
+                                                 skb->h.th->source);
        }
-
-       return secure_tcp_sequence_number(di, si,
-                                         skb->h.th->dest,
-                                         skb->h.th->source);
 }
 
 static int tcp_v6_check_established(struct sock *sk)
@@ -622,9 +619,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
         */
 
        if (!tp->write_seq)
-               tp->write_seq = secure_tcp_sequence_number(np->saddr.s6_addr32[3],
-                                                          np->daddr.s6_addr32[3],
-                                                          sk->sport, sk->dport);
+               tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
+                                                            np->daddr.s6_addr32,
+                                                            sk->sport, sk->dport);
 
        err = tcp_connect(sk, buff);
        if (err == 0)
index 88cd2a03bb10023ebb59e8c21140fef972d4961e..037d59d9236625b356f65156b6bd10ac8bcd0d74 100644 (file)
@@ -28,6 +28,7 @@
 #endif
 #include <net/pkt_sched.h>
 #include <net/scm.h>
+#include <linux/random.h>
 
 #ifdef CONFIG_BRIDGE
 #include <net/br.h>
@@ -235,7 +236,7 @@ EXPORT_SYMBOL(ip_options_compile);
 EXPORT_SYMBOL(ip_options_undo);
 EXPORT_SYMBOL(arp_send);
 EXPORT_SYMBOL(arp_broken_ops);
-EXPORT_SYMBOL(ip_id_count);
+EXPORT_SYMBOL(__ip_select_ident);
 EXPORT_SYMBOL(ip_send_check);
 EXPORT_SYMBOL(ip_fragment);
 EXPORT_SYMBOL(inet_family_ops);
@@ -376,6 +377,12 @@ EXPORT_SYMBOL(dev_loopback_xmit);
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_max_syn_backlog);
 #endif
+
+#if defined (CONFIG_IPV6_MODULE)
+EXPORT_SYMBOL(secure_tcpv6_sequence_number);
+EXPORT_SYMBOL(secure_ipv6_id);
+#endif
+
 #endif
 
 #ifdef CONFIG_NETLINK