diff -u --recursive --new-file v2.3.36/linux/CREDITS linux/CREDITS --- v2.3.36/linux/CREDITS Wed Dec 29 13:13:11 1999 +++ linux/CREDITS Thu Jan 6 10:23:46 2000 @@ -692,6 +692,9 @@ 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 diff -u --recursive --new-file v2.3.36/linux/Documentation/fb/clgenfb.txt linux/Documentation/fb/clgenfb.txt --- v2.3.36/linux/Documentation/fb/clgenfb.txt Mon Oct 11 15:38:14 1999 +++ linux/Documentation/fb/clgenfb.txt Thu Jan 6 10:23:46 2000 @@ -1,6 +1,6 @@ Framebuffer driver for Cirrus Logic chipsets - Copyright 1999 Jeff Garzik + Copyright 1999 Jeff Garzik diff -u --recursive --new-file v2.3.36/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt --- v2.3.36/linux/Documentation/networking/ip-sysctl.txt Mon May 10 09:55:25 1999 +++ linux/Documentation/networking/ip-sysctl.txt Thu Jan 6 10:14:36 2000 @@ -51,6 +51,36 @@ 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 @@ 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 $ diff -u --recursive --new-file v2.3.36/linux/Documentation/pci.txt linux/Documentation/pci.txt --- v2.3.36/linux/Documentation/pci.txt Tue Dec 7 09:32:38 1999 +++ linux/Documentation/pci.txt Thu Jan 6 09:54:06 2000 @@ -35,8 +35,13 @@ 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 -u --recursive --new-file v2.3.36/linux/Documentation/proc_usb_info.txt linux/Documentation/proc_usb_info.txt --- v2.3.36/linux/Documentation/proc_usb_info.txt Wed Dec 29 13:13:12 1999 +++ linux/Documentation/proc_usb_info.txt Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/CREDITS linux/Documentation/usb/CREDITS --- v2.3.36/linux/Documentation/usb/CREDITS Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/CREDITS Tue Jan 4 16:12:59 2000 @@ -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 + Johannes Erdfelt + ham + Bradley M Keryan + Paul Mackerras + David E. Nelson + Vojtech Pavlik + Gregory P. Smith + Linus Torvalds + Roman Weissgaerber + + +Special thanks to: + + Inaky Perez Gonzalez 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 , for standing so patiently + all my doubts'bout USB and giving lots of cool ideas. + + - Jochen Karrer , for + pointing out mortal bugs and giving advice. + + - Edmund Humemberger , for it's great work on + public relationships and general management stuff for the + Linux-USB effort. + + - Alberto Menegazzi is starting the + documentation for the UUSBD. Go for it! + + - Ric Klaren for doing nice + introductory documents (compiting with Alberto's :). + + - Christian Groessler , 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 has taken + charge of composing, maintaining and feeding the + long-awaited, unique and marvelous UUSBD FAQ! Tadaaaa!!! + + - Rasca Gmelch has revived the raw driver and + pointed bugs, as well as started the uusbd-utils package. + + - Peter Dettori 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 , 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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/URB.txt linux/Documentation/usb/URB.txt --- v2.3.36/linux/Documentation/usb/URB.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/URB.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/acm.txt linux/Documentation/usb/acm.txt --- v2.3.36/linux/Documentation/usb/acm.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/acm.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/dc2xx.txt linux/Documentation/usb/dc2xx.txt --- v2.3.36/linux/Documentation/usb/dc2xx.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/dc2xx.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/error-codes.txt linux/Documentation/usb/error-codes.txt --- v2.3.36/linux/Documentation/usb/error-codes.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/error-codes.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/hid.txt linux/Documentation/usb/hid.txt --- v2.3.36/linux/Documentation/usb/hid.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/hid.txt Tue Jan 4 16:12:59 2000 @@ -0,0 +1,162 @@ + Linux HID driver v0.8 + (c) 1999 Vojtech Pavlik + (c) 1999 Andreas Gal + 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 , 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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/ohci-hcd.txt linux/Documentation/usb/ohci-hcd.txt --- v2.3.36/linux/Documentation/usb/ohci-hcd.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/ohci-hcd.txt Tue Jan 4 16:12:59 2000 @@ -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 + + * 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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.3.36/linux/Documentation/usb/ov511.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/ov511.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/proc_usb_info.txt linux/Documentation/usb/proc_usb_info.txt --- v2.3.36/linux/Documentation/usb/proc_usb_info.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/proc_usb_info.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/scanner-hp-sane.txt linux/Documentation/usb/scanner-hp-sane.txt --- v2.3.36/linux/Documentation/usb/scanner-hp-sane.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/scanner-hp-sane.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/scanner.txt linux/Documentation/usb/scanner.txt --- v2.3.36/linux/Documentation/usb/scanner.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/scanner.txt Tue Jan 4 16:12:59 2000 @@ -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 + 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 , 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 +#include +#include +#include +#include + +/* + 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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/uhci.txt linux/Documentation/usb/uhci.txt --- v2.3.36/linux/Documentation/usb/uhci.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/uhci.txt Tue Jan 4 16:12:59 2000 @@ -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 -u --recursive --new-file v2.3.36/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- v2.3.36/linux/Documentation/usb/usb-serial.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/usb-serial.txt Tue Jan 4 16:12:59 2000 @@ -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 + diff -u --recursive --new-file v2.3.36/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.36/linux/MAINTAINERS Tue Jan 4 13:57:16 2000 +++ linux/MAINTAINERS Thu Jan 6 10:23:46 2000 @@ -192,7 +192,7 @@ 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 @@ VIA 82Cxxx AUDIO DRIVER P: Jeff Garzik -M: jgarzik@pobox.com +M: jgarzik@mandrakesoft.com S: Maintained VIDEO FOR LINUX diff -u --recursive --new-file v2.3.36/linux/Makefile linux/Makefile --- v2.3.36/linux/Makefile Tue Jan 4 13:57:16 2000 +++ linux/Makefile Thu Jan 6 12:36:34 2000 @@ -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 @@ 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.36/linux/arch/alpha/kernel/osf_sys.c Tue Jan 4 13:57:16 2000 +++ linux/arch/alpha/kernel/osf_sys.c Thu Jan 6 10:14:36 2000 @@ -43,15 +43,9 @@ #include #include -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) diff -u --recursive --new-file v2.3.36/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c --- v2.3.36/linux/arch/alpha/kernel/sys_sio.c Tue Dec 7 09:32:40 1999 +++ linux/arch/alpha/kernel/sys_sio.c Thu Jan 6 09:54:06 2000 @@ -141,7 +141,7 @@ 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; diff -u --recursive --new-file v2.3.36/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- v2.3.36/linux/arch/arm/kernel/bios32.c Tue Dec 14 01:27:23 1999 +++ linux/arch/arm/kernel/bios32.c Thu Jan 6 09:54:06 2000 @@ -24,7 +24,7 @@ { 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S --- v2.3.36/linux/arch/i386/boot/setup.S Tue Dec 7 09:32:40 1999 +++ linux/arch/i386/boot/setup.S Tue Jan 4 18:28:26 2000 @@ -202,9 +202,9 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.3.36/linux/arch/i386/config.in Tue Jan 4 13:57:16 2000 +++ linux/arch/i386/config.in Thu Jan 6 10:16:48 2000 @@ -120,6 +120,12 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c --- v2.3.36/linux/arch/i386/kernel/acpi.c Wed Dec 29 13:13:12 1999 +++ linux/arch/i386/kernel/acpi.c Thu Jan 6 10:16:48 2000 @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -120,6 +121,9 @@ 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 @@ } 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 @@ { 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 @@ 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 @@ -1239,6 +1248,22 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.3.36/linux/arch/i386/kernel/apm.c Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/kernel/apm.c Thu Jan 6 10:16:48 2000 @@ -1491,6 +1491,13 @@ 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). diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.3.36/linux/arch/i386/kernel/i386_ksyms.c Tue Dec 7 09:32:40 1999 +++ linux/arch/i386/kernel/i386_ksyms.c Wed Jan 5 10:51:40 2000 @@ -56,6 +56,9 @@ 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); diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.3.36/linux/arch/i386/kernel/irq.c Tue Jan 4 13:57:16 2000 +++ linux/arch/i386/kernel/irq.c Wed Jan 5 17:42:08 2000 @@ -707,9 +707,11 @@ } 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; } diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c --- v2.3.36/linux/arch/i386/kernel/pci-i386.c Tue Jan 4 13:57:16 2000 +++ linux/arch/i386/kernel/pci-i386.c Thu Jan 6 09:54:06 2000 @@ -12,7 +12,7 @@ * Hannover, Germany * hm@ix.de * - * Copyright 1997--1999 Martin Mares + * Copyright 1997--2000 Martin Mares * * For more information, please consult the following manuals (look at * http://www.pcisig.com/ for how to get them): @@ -180,14 +180,17 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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(); diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c --- v2.3.36/linux/arch/i386/kernel/pci-pc.c Tue Jan 4 13:57:16 2000 +++ linux/arch/i386/kernel/pci-pc.c Thu Jan 6 09:54:06 2000 @@ -1,7 +1,7 @@ /* * Low-Level PCI Support for PC * - * (c) 1999 Martin Mares + * (c) 1999--2000 Martin Mares */ #include @@ -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 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 @@ 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 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } 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) diff -u --recursive --new-file v2.3.36/linux/arch/i386/kernel/pci-visws.c linux/arch/i386/kernel/pci-visws.c --- v2.3.36/linux/arch/i386/kernel/pci-visws.c Tue Dec 7 09:32:40 1999 +++ linux/arch/i386/kernel/pci-visws.c Thu Jan 6 09:54:06 2000 @@ -1,7 +1,7 @@ /* * Low-Level PCI Support for SGI Visual Workstation * - * (c) 1999 Martin Mares + * (c) 1999--2000 Martin Mares */ #include @@ -85,7 +85,7 @@ 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) diff -u --recursive --new-file v2.3.36/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c --- v2.3.36/linux/arch/m68k/kernel/bios32.c Tue Aug 31 17:29:12 1999 +++ linux/arch/m68k/kernel/bios32.c Thu Jan 6 09:54:06 2000 @@ -449,69 +449,6 @@ #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 @@ * 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; diff -u --recursive --new-file v2.3.36/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.3.36/linux/arch/mips/sni/pci.c Sat Oct 9 11:47:50 1999 +++ linux/arch/mips/sni/pci.c Thu Jan 6 09:54:06 2000 @@ -30,7 +30,7 @@ { 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. diff -u --recursive --new-file v2.3.36/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c --- v2.3.36/linux/arch/ppc/kernel/chrp_pci.c Wed Oct 27 16:34:12 1999 +++ linux/arch/ppc/kernel/chrp_pci.c Thu Jan 6 09:54:06 2000 @@ -282,8 +282,7 @@ } /* 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 */ diff -u --recursive --new-file v2.3.36/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.3.36/linux/arch/ppc/kernel/pci.c Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/pci.c Thu Jan 6 09:54:06 2000 @@ -91,15 +91,17 @@ 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 @@ } } } - if (bus->children) - pcibios_claim_resources(bus->children); - bus = bus->next; + pcibios_claim_resources(&bus->children); } } diff -u --recursive --new-file v2.3.36/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c --- v2.3.36/linux/arch/ppc/kernel/pmac_pci.c Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/pmac_pci.c Thu Jan 6 09:54:06 2000 @@ -476,7 +476,7 @@ * 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, diff -u --recursive --new-file v2.3.36/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c --- v2.3.36/linux/arch/ppc/kernel/prep_pci.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/prep_pci.c Thu Jan 6 09:54:06 2000 @@ -998,7 +998,7 @@ 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.3.36/linux/arch/sparc/kernel/sys_sunos.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc/kernel/sys_sunos.c Thu Jan 6 10:14:36 2000 @@ -721,7 +721,7 @@ }; -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 @@ 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.3.36/linux/arch/sparc64/kernel/sys_sunos32.c Wed Dec 29 13:13:14 1999 +++ linux/arch/sparc64/kernel/sys_sunos32.c Thu Jan 6 10:14:36 2000 @@ -685,7 +685,7 @@ 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 @@ 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 @@ 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 */ diff -u --recursive --new-file v2.3.36/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c --- v2.3.36/linux/drivers/acorn/block/fd1772.c Mon Aug 2 10:19:52 1999 +++ linux/drivers/acorn/block/fd1772.c Wed Jan 5 07:01:22 2000 @@ -1350,10 +1350,6 @@ 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 @@ RO_IOCTLS(inode->i_rdev, param); } drive = MINOR(device); - if (!IOCTL_ALLOWED) - return -EPERM; switch (cmd) { case FDFMTBEG: return 0; @@ -1544,12 +1538,6 @@ 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 @@ { 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; diff -u --recursive --new-file v2.3.36/linux/drivers/block/alim15x3.c linux/drivers/block/alim15x3.c --- v2.3.36/linux/drivers/block/alim15x3.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/block/alim15x3.c Thu Jan 6 09:54:06 2000 @@ -609,23 +609,13 @@ 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) { /* diff -u --recursive --new-file v2.3.36/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.3.36/linux/drivers/block/ataflop.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/ataflop.c Wed Jan 5 07:01:22 2000 @@ -1559,10 +1559,6 @@ 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 @@ return -EFAULT; return 0; } - if (!IOCTL_ALLOWED) - return -EPERM; switch (cmd) { case FDSETPRM: case FDDEFPRM: @@ -1928,12 +1922,6 @@ 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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.3.36/linux/drivers/block/floppy.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/floppy.c Wed Jan 5 07:01:22 2000 @@ -3387,9 +3387,6 @@ 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 @@ return -EINVAL; /* permission checks */ - if (((cmd & 0x40) && !IOCTL_ALLOWED) || - ((cmd & 0x80) && !suser())) + if ((cmd & 0x80) && !suser()) return -EPERM; /* copyin */ @@ -3578,7 +3574,6 @@ return fd_copyout((void *)param, outparam, size); else return 0; -#undef IOCTL_ALLOWED #undef OUT #undef IN } @@ -3630,53 +3625,13 @@ 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 @@ 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 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 */ diff -u --recursive --new-file v2.3.36/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c --- v2.3.36/linux/drivers/block/ide-pci.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/block/ide-pci.c Thu Jan 6 09:54:06 2000 @@ -635,7 +635,7 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.3.36/linux/drivers/block/loop.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/loop.c Thu Jan 6 10:14:36 2000 @@ -375,7 +375,10 @@ } 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 @@ 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) { diff -u --recursive --new-file v2.3.36/linux/drivers/block/swim3.c linux/drivers/block/swim3.c --- v2.3.36/linux/drivers/block/swim3.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/swim3.c Wed Jan 5 07:01:22 2000 @@ -250,9 +250,6 @@ 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 @@ 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 @@ 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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/drivers/block/swim_iop.c linux/drivers/block/swim_iop.c --- v2.3.36/linux/drivers/block/swim_iop.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/swim_iop.c Wed Jan 5 07:01:22 2000 @@ -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 @@ 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 @@ 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 @@ 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--; diff -u --recursive --new-file v2.3.36/linux/drivers/block/via82cxxx.c linux/drivers/block/via82cxxx.c --- v2.3.36/linux/drivers/block/via82cxxx.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/block/via82cxxx.c Thu Jan 6 10:23:46 2000 @@ -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 * diff -u --recursive --new-file v2.3.36/linux/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c --- v2.3.36/linux/drivers/char/agp/agpgart_fe.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/char/agp/agpgart_fe.c Thu Jan 6 10:23:46 2000 @@ -1094,5 +1094,6 @@ void agp_frontend_cleanup(void) { + misc_deregister(&agp_miscdev); return; } diff -u --recursive --new-file v2.3.36/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.3.36/linux/drivers/char/bttv.c Tue Jan 4 13:57:16 2000 +++ linux/drivers/char/bttv.c Thu Jan 6 09:54:06 2000 @@ -3465,13 +3465,12 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.3.36/linux/drivers/char/random.c Mon Oct 4 15:49:29 1999 +++ linux/drivers/char/random.c Thu Jan 6 10:14:36 2000 @@ -1936,7 +1936,7 @@ /* 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 @@ #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< 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) { @@ -2052,6 +2105,38 @@ saddr, daddr, sport, dport, seq); #endif return seq; +} + +/* The code below is shamelessly stolen from secure_tcp_sequence_number(). + * All blames to Andrey V. Savochkin . + */ +__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 diff -u --recursive --new-file v2.3.36/linux/drivers/char/raw.c linux/drivers/char/raw.c --- v2.3.36/linux/drivers/char/raw.c Fri Oct 15 15:25:13 1999 +++ linux/drivers/char/raw.c Thu Jan 6 10:14:36 2000 @@ -18,13 +18,11 @@ #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 @@ 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 @@ 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 @@ */ 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 @@ */ 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_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 @@ 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 @@ */ 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; diff -u --recursive --new-file v2.3.36/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.3.36/linux/drivers/char/serial.c Wed Dec 29 13:13:15 1999 +++ linux/drivers/char/serial.c Thu Jan 6 09:54:06 2000 @@ -3990,7 +3990,6 @@ */ 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 @@ 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 @@ 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; } diff -u --recursive --new-file v2.3.36/linux/drivers/char/stradis.c linux/drivers/char/stradis.c --- v2.3.36/linux/drivers/char/stradis.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/char/stradis.c Thu Jan 6 09:54:06 2000 @@ -2243,26 +2243,19 @@ 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); diff -u --recursive --new-file v2.3.36/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c --- v2.3.36/linux/drivers/i2o/i2o_pci.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/i2o/i2o_pci.c Thu Jan 6 09:54:06 2000 @@ -229,9 +229,8 @@ 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) diff -u --recursive --new-file v2.3.36/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.3.36/linux/drivers/macintosh/via-pmu.c Fri Oct 15 15:25:13 1999 +++ linux/drivers/macintosh/via-pmu.c Thu Jan 6 09:54:06 2000 @@ -1047,8 +1047,9 @@ 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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c --- v2.3.36/linux/drivers/net/pcmcia/ray_cs.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/net/pcmcia/ray_cs.c Wed Jan 5 10:34:02 2000 @@ -2529,13 +2529,23 @@ * 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 @@ } 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/drivers/net/pcmcia/tulip_cb.c linux/drivers/net/pcmcia/tulip_cb.c --- v2.3.36/linux/drivers/net/pcmcia/tulip_cb.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/net/pcmcia/tulip_cb.c Wed Jan 5 15:55:10 2000 @@ -3324,10 +3324,10 @@ 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; } diff -u --recursive --new-file v2.3.36/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.3.36/linux/drivers/parport/parport_pc.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/parport/parport_pc.c Thu Jan 6 09:54:06 2000 @@ -1828,7 +1828,7 @@ } /* 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; diff -u --recursive --new-file v2.3.36/linux/drivers/pci/compat.c linux/drivers/pci/compat.c --- v2.3.36/linux/drivers/pci/compat.c Tue Dec 7 09:32:44 1999 +++ linux/drivers/pci/compat.c Thu Jan 6 09:54:06 2000 @@ -3,7 +3,7 @@ * * PCI Bus Services -- Function For Backward Compatibility * - * Copyright 1998, 1999 Martin Mares + * Copyright 1998--2000 Martin Mares */ #include @@ -13,7 +13,7 @@ int pcibios_present(void) { - return !!pci_devices; + return pci_devices.next != &pci_devices; } int diff -u --recursive --new-file v2.3.36/linux/drivers/pci/helper.c linux/drivers/pci/helper.c --- v2.3.36/linux/drivers/pci/helper.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/pci/helper.c Thu Jan 6 10:24:04 2000 @@ -3,7 +3,7 @@ * * drivers/pci/helper.c * - * Copyright 1999 Jeff Garzik + * Copyright 1999 Jeff Garzik * This software is free. See the file COPYING for licensing details. * */ diff -u --recursive --new-file v2.3.36/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.3.36/linux/drivers/pci/pci.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/pci/pci.c Thu Jan 6 09:54:06 2000 @@ -6,7 +6,7 @@ * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter, * David Mosberger-Tang * - * Copyright 1997 -- 1999 Martin Mares + * Copyright 1997 -- 2000 Martin Mares */ #include @@ -27,19 +27,19 @@ #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 @@ 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 @@ 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 @@ } } +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 @@ /* * 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 @@ /* * 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 @@ /* * 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ * * 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 @@ 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) diff -u --recursive --new-file v2.3.36/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.3.36/linux/drivers/pci/pci.ids Wed Dec 29 13:13:16 1999 +++ linux/drivers/pci/pci.ids Thu Jan 6 09:54:06 2000 @@ -4,7 +4,7 @@ # Maintained by Martin Mares # 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. @@ -778,7 +778,8 @@ 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 @@ -865,13 +866,14 @@ 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 @@ -1012,17 +1014,23 @@ 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 @@ -2108,6 +2116,8 @@ 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 @@ -2295,7 +2305,8 @@ 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 @@ -3271,6 +3282,7 @@ 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 diff -u --recursive --new-file v2.3.36/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c --- v2.3.36/linux/drivers/pci/pcisyms.c Wed Dec 29 13:13:17 1999 +++ linux/drivers/pci/pcisyms.c Thu Jan 6 09:54:06 2000 @@ -18,7 +18,7 @@ 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_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); diff -u --recursive --new-file v2.3.36/linux/drivers/pci/proc.c linux/drivers/pci/proc.c --- v2.3.36/linux/drivers/pci/proc.c Wed Dec 8 14:11:26 1999 +++ linux/drivers/pci/proc.c Thu Jan 6 09:54:06 2000 @@ -218,12 +218,12 @@ 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 @@ cnt += len; buf += len; } - dev = dev->next; } return (count > cnt) ? cnt : count; } @@ -289,18 +288,6 @@ 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 @@ 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 @@ 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 __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; diff -u --recursive --new-file v2.3.36/linux/drivers/pci/setup.c linux/drivers/pci/setup.c --- v2.3.36/linux/drivers/pci/setup.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/pci/setup.c Thu Jan 6 09:54:06 2000 @@ -144,8 +144,10 @@ 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 @@ 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 @@ } /* 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 @@ 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c --- v2.3.36/linux/drivers/pcmcia/cardbus.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/pcmcia/cardbus.c Thu Jan 6 09:54:06 2000 @@ -267,8 +267,8 @@ 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 @@ 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 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 @@ 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 @@ 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; ifunctions; 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); diff -u --recursive --new-file v2.3.36/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.3.36/linux/drivers/pcmcia/yenta.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/pcmcia/yenta.c Wed Jan 5 16:11:46 2000 @@ -428,13 +428,18 @@ /* 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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c --- v2.3.36/linux/drivers/pnp/isapnp.c Tue Dec 7 09:32:45 1999 +++ linux/drivers/pnp/isapnp.c Thu Jan 6 11:39:35 2000 @@ -39,6 +39,9 @@ #include #include +LIST_HEAD(isapnp_cards); +LIST_HEAD(isapnp_devices); + #ifdef CONFIG_PROC_FS #include "isapnp_proc.c" #endif @@ -108,9 +111,6 @@ #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 @@ { 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 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 @@ 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_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 @@ 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 @@ { 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 @@ 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 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 @@ 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 @@ } 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) { diff -u --recursive --new-file v2.3.36/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c --- v2.3.36/linux/drivers/pnp/isapnp_proc.c Tue Dec 7 09:32:45 1999 +++ linux/drivers/pnp/isapnp_proc.c Thu Jan 6 10:54:12 2000 @@ -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_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 @@ 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_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; diff -u --recursive --new-file v2.3.36/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.3.36/linux/drivers/scsi/megaraid.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/scsi/megaraid.c Thu Jan 6 09:54:06 2000 @@ -1411,37 +1411,27 @@ { 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 @@ 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 */ diff -u --recursive --new-file v2.3.36/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.3.36/linux/drivers/sound/es1370.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/sound/es1370.c Wed Jan 5 08:22:31 2000 @@ -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 @@ -52,68 +52,68 @@ * 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 - * 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 - * 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 - * 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 - * 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 - * 15.06.99 0.23 Fix bad allocation bug. - * Thanks to Deti Fliegl - * 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 - * 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 + * 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 + * 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 + * 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 + * 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 + * 15.06.1999 0.23 Fix bad allocation bug. + * Thanks to Deti Fliegl + * 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 + * 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: * diff -u --recursive --new-file v2.3.36/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.3.36/linux/drivers/sound/es1371.c Tue Dec 7 09:32:46 1999 +++ linux/drivers/sound/es1371.c Wed Jan 5 08:22:31 2000 @@ -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 @@ -38,62 +38,64 @@ * 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 - * 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 - * Another Alpha fix (wait_src_ready in init routine) - * reported by "Ivan N. Kokshaysky" - * 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 - * 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 . - * module_init/__setup fixes - * 08.16.99 0.16 Joe Cotellese - * 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 - * 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 - * 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 + * 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 + * Another Alpha fix (wait_src_ready in init routine) + * reported by "Ivan N. Kokshaysky" + * 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 + * 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 . + * module_init/__setup fixes + * 08.16.1999 0.16 Joe Cotellese + * 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 + * 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 + * 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 @@ 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.3.36/linux/drivers/sound/esssolo1.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/sound/esssolo1.c Wed Jan 5 08:22:31 2000 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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) || diff -u --recursive --new-file v2.3.36/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c --- v2.3.36/linux/drivers/sound/nm256_audio.c Wed Oct 27 16:34:12 1999 +++ linux/drivers/sound/nm256_audio.c Wed Jan 5 10:47:14 2000 @@ -45,14 +45,7 @@ #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; diff -u --recursive --new-file v2.3.36/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.3.36/linux/drivers/sound/sonicvibes.c Wed Dec 8 14:11:26 1999 +++ linux/drivers/sound/sonicvibes.c Wed Jan 5 08:22:31 2000 @@ -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 @@ -35,55 +35,55 @@ * 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 - * 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 - * 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 - * 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 + * 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 + * 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 + * 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 -u --recursive --new-file v2.3.36/linux/drivers/usb/CREDITS linux/drivers/usb/CREDITS --- v2.3.36/linux/drivers/usb/CREDITS Sun Nov 7 16:37:34 1999 +++ linux/drivers/usb/CREDITS Wed Dec 31 16:00:00 1969 @@ -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 - Johannes Erdfelt - ham - Bradley M Keryan - Paul Mackerras - David E. Nelson - Vojtech Pavlik - Gregory P. Smith - Linus Torvalds - Roman Weissgaerber - - -Special thanks to: - - Inaky Perez Gonzalez 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 , for standing so patiently - all my doubts'bout USB and giving lots of cool ideas. - - - Jochen Karrer , for - pointing out mortal bugs and giving advice. - - - Edmund Humemberger , for it's great work on - public relationships and general management stuff for the - Linux-USB effort. - - - Alberto Menegazzi is starting the - documentation for the UUSBD. Go for it! - - - Ric Klaren for doing nice - introductory documents (compiting with Alberto's :). - - - Christian Groessler , 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 has taken - charge of composing, maintaining and feeding the - long-awaited, unique and marvelous UUSBD FAQ! Tadaaaa!!! - - - Rasca Gmelch has revived the raw driver and - pointed bugs, as well as started the uusbd-utils package. - - - Peter Dettori 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 , 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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.URB linux/drivers/usb/README.URB --- v2.3.36/linux/drivers/usb/README.URB Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/README.URB Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.acm linux/drivers/usb/README.acm --- v2.3.36/linux/drivers/usb/README.acm Mon Aug 2 14:29:08 1999 +++ linux/drivers/usb/README.acm Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.dc2xx linux/drivers/usb/README.dc2xx --- v2.3.36/linux/drivers/usb/README.dc2xx Tue Nov 23 22:42:21 1999 +++ linux/drivers/usb/README.dc2xx Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.error-codes linux/drivers/usb/README.error-codes --- v2.3.36/linux/drivers/usb/README.error-codes Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/README.error-codes Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.hid linux/drivers/usb/README.hid --- v2.3.36/linux/drivers/usb/README.hid Tue Jan 4 13:57:17 2000 +++ linux/drivers/usb/README.hid Wed Dec 31 16:00:00 1969 @@ -1,162 +0,0 @@ - Linux HID driver v0.8 - (c) 1999 Vojtech Pavlik - (c) 1999 Andreas Gal - 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 , 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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.ohci_hcd linux/drivers/usb/README.ohci_hcd --- v2.3.36/linux/drivers/usb/README.ohci_hcd Wed Aug 18 16:22:23 1999 +++ linux/drivers/usb/README.ohci_hcd Wed Dec 31 16:00:00 1969 @@ -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 - - * 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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.ov511 linux/drivers/usb/README.ov511 --- v2.3.36/linux/drivers/usb/README.ov511 Tue Jan 4 13:57:17 2000 +++ linux/drivers/usb/README.ov511 Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.scanner linux/drivers/usb/README.scanner --- v2.3.36/linux/drivers/usb/README.scanner Wed Dec 29 13:13:19 1999 +++ linux/drivers/usb/README.scanner Wed Dec 31 16:00:00 1969 @@ -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 - 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 , 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 -#include -#include -#include -#include - -/* - 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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.scanner_hp_sane linux/drivers/usb/README.scanner_hp_sane --- v2.3.36/linux/drivers/usb/README.scanner_hp_sane Wed Dec 29 13:13:19 1999 +++ linux/drivers/usb/README.scanner_hp_sane Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.serial linux/drivers/usb/README.serial --- v2.3.36/linux/drivers/usb/README.serial Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/README.serial Wed Dec 31 16:00:00 1969 @@ -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 -u --recursive --new-file v2.3.36/linux/drivers/usb/README.uhci linux/drivers/usb/README.uhci --- v2.3.36/linux/drivers/usb/README.uhci Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/README.uhci Wed Dec 31 16:00:00 1969 @@ -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. diff -u --recursive --new-file v2.3.36/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c --- v2.3.36/linux/drivers/usb/ohci-hcd.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/ohci-hcd.c Wed Jan 5 08:44:47 2000 @@ -334,7 +334,7 @@ /* 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 @@ 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 @@ { ohci_t * ohci = usb_dev->bus->hcpriv; - return ohci->hcca.frame_no; + return le16_to_cpu (ohci->hcca.frame_no); } /*-------------------------------------------------------------------------*/ @@ -775,7 +777,7 @@ 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 @@ 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 @@ 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 (®s->intrstatus) & readl (®s->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, ®s->intrdisable); @@ -1548,7 +1550,7 @@ } 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, ®s->intrdisable); if (ohci->ed_rm_list[!frame] != NULL) { dl_del_list (ohci, !frame); diff -u --recursive --new-file v2.3.36/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.3.36/linux/drivers/usb/ov511.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/usb/ov511.c Wed Jan 5 08:44:47 2000 @@ -14,7 +14,22 @@ * 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__ @@ -46,13 +61,15 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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; + + /* 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; - 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 @@ break; case 993: alt = 1; - multiplier = 32; + multiplier = 31; break; case 768: alt = 2; @@ -311,7 +355,7 @@ break; case 769: alt = 3; - multiplier = 25; + multiplier = 24; break; case 512: alt = 4; @@ -319,11 +363,11 @@ 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 @@ 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 @@ } // 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 @@ /* 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) +static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb) { - PDEBUG("ov511_parse_data not implemented\n"); // TEMPORARY CODE -} - -static int ov511_compress_isochronous(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 @@ 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 @@ } 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 @@ } 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 @@ /* 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 @@ 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 @@ 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 @@ ov511->streaming = 1; - return 0; + return 0; } @@ -518,14 +626,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h --- v2.3.36/linux/drivers/usb/ov511.h Tue Jan 4 13:57:17 2000 +++ linux/drivers/usb/ov511.h Wed Jan 5 08:44:47 2000 @@ -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 @@ -109,7 +109,7 @@ #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 */ @@ -118,6 +118,7 @@ // 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 @@ 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 */ diff -u --recursive --new-file v2.3.36/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c --- v2.3.36/linux/drivers/usb/usb_scsi.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/usb_scsi.c Thu Jan 6 10:36:19 2000 @@ -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. * @@ -47,12 +45,14 @@ #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 -u --recursive --new-file v2.3.36/linux/drivers/usb/usb_scsi_dt.c linux/drivers/usb/usb_scsi_dt.c --- v2.3.36/linux/drivers/usb/usb_scsi_dt.c Mon Jun 7 20:04:01 1999 +++ linux/drivers/usb/usb_scsi_dt.c Wed Dec 31 16:00:00 1969 @@ -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 diff -u --recursive --new-file v2.3.36/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c --- v2.3.36/linux/drivers/video/aty128fb.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/video/aty128fb.c Thu Jan 6 09:54:06 2000 @@ -1598,14 +1598,13 @@ 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 */ diff -u --recursive --new-file v2.3.36/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.3.36/linux/drivers/video/atyfb.c Wed Dec 29 13:13:20 1999 +++ linux/drivers/video/atyfb.c Thu Jan 6 10:32:49 2000 @@ -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 @@ */ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ if(!info->ati_regbase) { kfree(info); + release_mem_region(res_start, res_size); return -ENOMEM; } @@ -3913,6 +3913,7 @@ if(!info->frame_buffer) { kfree(info); + release_mem_region(res_start, res_size); return -ENXIO; } @@ -3922,6 +3923,7 @@ if (info->mmap_map) kfree(info->mmap_map); kfree(info); + release_mem_region(res_start, res_size); return -ENXIO; } @@ -3943,6 +3945,18 @@ 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 */ } } @@ -4002,114 +4016,6 @@ #endif /* CONFIG_ATARI */ 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) diff -u --recursive --new-file v2.3.36/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c --- v2.3.36/linux/drivers/video/clgenfb.c Mon Nov 1 13:56:27 1999 +++ linux/drivers/video/clgenfb.c Thu Jan 6 10:30:52 2000 @@ -1,7 +1,7 @@ /* * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets * - * Copyright 1999 Jeff Garzik + * Copyright 1999 Jeff Garzik * * Contributors (thanks, all!) * @@ -2594,10 +2594,10 @@ { 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 @@ #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 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 @@ 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 @@ */ #ifdef MODULE -MODULE_AUTHOR("Copyright 1999 Jeff Garzik "); +MODULE_AUTHOR("Copyright 1999 Jeff Garzik "); MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); int init_module (void) diff -u --recursive --new-file v2.3.36/linux/drivers/video/clgenfb.h linux/drivers/video/clgenfb.h --- v2.3.36/linux/drivers/video/clgenfb.h Wed Aug 18 10:10:06 1999 +++ linux/drivers/video/clgenfb.h Thu Jan 6 10:23:46 2000 @@ -1,7 +1,7 @@ /* * drivers/video/clgenfb.h - Cirrus Logic chipset constants * - * Copyright 1999 Jeff Garzik + * Copyright 1999 Jeff Garzik * * Original clgenfb author: Frank Neumann * diff -u --recursive --new-file v2.3.36/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c --- v2.3.36/linux/drivers/video/fbmem.c Wed Dec 29 13:13:20 1999 +++ linux/drivers/video/fbmem.c Thu Jan 6 10:31:38 2000 @@ -143,14 +143,18 @@ #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 }, diff -u --recursive --new-file v2.3.36/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c --- v2.3.36/linux/drivers/video/imsttfb.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/video/imsttfb.c Thu Jan 6 09:54:06 2000 @@ -1919,21 +1919,15 @@ /* 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) diff -u --recursive --new-file v2.3.36/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c --- v2.3.36/linux/drivers/video/matroxfb.c Tue Nov 23 22:42:21 1999 +++ linux/drivers/video/matroxfb.c Thu Jan 6 09:54:06 2000 @@ -2559,14 +2559,6 @@ }; #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 @@ 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) diff -u --recursive --new-file v2.3.36/linux/drivers/video/offb.c linux/drivers/video/offb.c --- v2.3.36/linux/drivers/video/offb.c Fri Oct 22 13:21:51 1999 +++ linux/drivers/video/offb.c Thu Jan 6 10:31:38 2000 @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef CONFIG_FB_COMPAT_XPMAC #include #endif @@ -290,9 +291,6 @@ } -#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 @@ 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 @@ 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 @@ 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 @@ 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 @@ if (register_framebuffer(&info->info) < 0) { kfree(info); + release_mem_region(res_start, res_size); return; } diff -u --recursive --new-file v2.3.36/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c --- v2.3.36/linux/drivers/video/pm2fb.c Wed Dec 29 13:13:20 1999 +++ linux/drivers/video/pm2fb.c Thu Jan 6 10:30:52 2000 @@ -921,8 +921,8 @@ 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 @@ #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 @@ } 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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/drivers/video/rivafb.c linux/drivers/video/rivafb.c --- v2.3.36/linux/drivers/video/rivafb.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/video/rivafb.c Thu Jan 6 10:30:52 2000 @@ -1,7 +1,7 @@ /* * linux/drivers/video/rivafb.c - nVidia RIVA 128/TNT/TNT2 fb driver * - * Copyright 1999 Jeff Garzik + * Copyright 1999 Jeff Garzik * * Contributors: * @@ -622,12 +622,12 @@ 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; } diff -u --recursive --new-file v2.3.36/linux/drivers/video/tdfxfb.c linux/drivers/video/tdfxfb.c --- v2.3.36/linux/drivers/video/tdfxfb.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/video/tdfxfb.c Thu Jan 6 09:54:06 2000 @@ -1969,9 +1969,8 @@ 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 diff -u --recursive --new-file v2.3.36/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c --- v2.3.36/linux/drivers/video/vesafb.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/video/vesafb.c Thu Jan 6 10:30:52 2000 @@ -541,8 +541,7 @@ 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 @@ /* 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); diff -u --recursive --new-file v2.3.36/linux/drivers/video/vga.h linux/drivers/video/vga.h --- v2.3.36/linux/drivers/video/vga.h Thu Aug 26 13:05:40 1999 +++ linux/drivers/video/vga.h Thu Jan 6 10:23:46 2000 @@ -1,7 +1,7 @@ /* * linux/include/video/vga.h -- standard VGA chipset interaction * - * Copyright 1999 Jeff Garzik + * Copyright 1999 Jeff Garzik * * Copyright history from vga16fb.c: * Copyright 1999 Ben Pfaff and Petr Vandrovec diff -u --recursive --new-file v2.3.36/linux/drivers/video/vga16fb.c linux/drivers/video/vga16fb.c --- v2.3.36/linux/drivers/video/vga16fb.c Thu Aug 26 13:05:40 1999 +++ linux/drivers/video/vga16fb.c Thu Jan 6 10:30:52 2000 @@ -924,8 +924,7 @@ 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 @@ /* 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 @@ { 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 diff -u --recursive --new-file v2.3.36/linux/fs/block_dev.c linux/fs/block_dev.c --- v2.3.36/linux/fs/block_dev.c Tue Jun 22 10:45:40 1999 +++ linux/fs/block_dev.c Thu Jan 6 10:14:36 2000 @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include @@ -299,3 +301,351 @@ { 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 */ +}; diff -u --recursive --new-file v2.3.36/linux/fs/devices.c linux/fs/devices.c --- v2.3.36/linux/fs/devices.c Tue Jan 4 13:57:17 2000 +++ linux/fs/devices.c Thu Jan 6 10:14:36 2000 @@ -37,9 +37,7 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ 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 @@ } 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 diff -u --recursive --new-file v2.3.36/linux/fs/fifo.c linux/fs/fifo.c --- v2.3.36/linux/fs/fifo.c Tue Dec 7 09:32:47 1999 +++ linux/fs/fifo.c Thu Jan 6 10:14:36 2000 @@ -170,11 +170,3 @@ 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; -} diff -u --recursive --new-file v2.3.36/linux/fs/inode.c linux/fs/inode.c --- v2.3.36/linux/fs/inode.c Tue Nov 23 22:42:21 1999 +++ linux/fs/inode.c Thu Jan 6 10:14:36 2000 @@ -257,7 +257,10 @@ 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 @@ inode->i_generation = 0; memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); inode->i_pipe = NULL; + inode->i_bdev = NULL; } /* diff -u --recursive --new-file v2.3.36/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v2.3.36/linux/fs/isofs/inode.c Mon Dec 20 18:48:22 1999 +++ linux/fs/isofs/inode.c Thu Jan 6 10:14:36 2000 @@ -425,71 +425,54 @@ */ #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 @@ 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++) diff -u --recursive --new-file v2.3.36/linux/fs/super.c linux/fs/super.c --- v2.3.36/linux/fs/super.c Tue Jan 4 13:57:18 2000 +++ linux/fs/super.c Thu Jan 6 10:14:36 2000 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ * 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 @@ * 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 @@ * 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 @@ */ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } #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 @@ 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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/fs/udf/inode.c linux/fs/udf/inode.c --- v2.3.36/linux/fs/udf/inode.c Tue Jan 4 13:57:18 2000 +++ linux/fs/udf/inode.c Thu Jan 6 10:14:36 2000 @@ -1157,7 +1157,7 @@ } 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: diff -u --recursive --new-file v2.3.36/linux/fs/udf/lowlevel.c linux/fs/udf/lowlevel.c --- v2.3.36/linux/fs/udf/lowlevel.c Tue Nov 23 22:42:21 1999 +++ linux/fs/udf/lowlevel.c Thu Jan 6 10:14:36 2000 @@ -38,60 +38,36 @@ #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 @@ 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; } diff -u --recursive --new-file v2.3.36/linux/fs/udf/super.c linux/fs/udf/super.c --- v2.3.36/linux/fs/udf/super.c Tue Nov 23 22:42:21 1999 +++ linux/fs/udf/super.c Thu Jan 6 10:14:36 2000 @@ -1335,14 +1335,14 @@ 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; diff -u --recursive --new-file v2.3.36/linux/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h --- v2.3.36/linux/fs/udf/udfdecl.h Tue Nov 23 22:42:21 1999 +++ linux/fs/udf/udfdecl.h Thu Jan 6 10:14:36 2000 @@ -158,8 +158,8 @@ 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); diff -u --recursive --new-file v2.3.36/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h --- v2.3.36/linux/include/asm-i386/semaphore.h Tue Dec 7 09:32:49 1999 +++ linux/include/asm-i386/semaphore.h Thu Jan 6 11:42:19 2000 @@ -258,9 +258,9 @@ } /* 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) { diff -u --recursive --new-file v2.3.36/linux/include/linux/acpi.h linux/include/linux/acpi.h --- v2.3.36/linux/include/linux/acpi.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/acpi.h Thu Jan 6 11:43:17 2000 @@ -174,6 +174,8 @@ } } +extern int acpi_active; + #else /* CONFIG_ACPI */ extern inline struct acpi_dev* diff -u --recursive --new-file v2.3.36/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.3.36/linux/include/linux/fs.h Tue Jan 4 13:57:21 2000 +++ linux/include/linux/fs.h Thu Jan 6 11:42:19 2000 @@ -340,6 +340,16 @@ 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 @@ 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 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 @@ #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 * 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 *); diff -u --recursive --new-file v2.3.36/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.3.36/linux/include/linux/pci.h Tue Jan 4 13:57:21 2000 +++ linux/include/linux/pci.h Thu Jan 6 11:42:18 2000 @@ -283,6 +283,7 @@ #include #include #include +#include #include @@ -295,13 +296,10 @@ * 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 @@ 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 @@ #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 @@ 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 @@ 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,11 +482,15 @@ 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) */ diff -u --recursive --new-file v2.3.36/linux/include/linux/random.h linux/include/linux/random.h --- v2.3.36/linux/include/linux/random.h Tue Aug 31 17:29:14 1999 +++ linux/include/linux/random.h Thu Jan 6 10:14:36 2000 @@ -54,6 +54,7 @@ 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 @@ __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; diff -u --recursive --new-file v2.3.36/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h --- v2.3.36/linux/include/linux/rtnetlink.h Thu Aug 26 13:05:41 1999 +++ linux/include/linux/rtnetlink.h Thu Jan 6 10:14:36 2000 @@ -249,6 +249,11 @@ __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_* */ diff -u --recursive --new-file v2.3.36/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.3.36/linux/include/linux/sysctl.h Tue Dec 7 09:32:51 1999 +++ linux/include/linux/sysctl.h Thu Jan 6 10:14:36 2000 @@ -245,6 +245,11 @@ 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 -u --recursive --new-file v2.3.36/linux/include/net/inetpeer.h linux/include/net/inetpeer.h --- v2.3.36/linux/include/net/inetpeer.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/inetpeer.h Thu Jan 6 11:43:38 2000 @@ -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 + */ + +#ifndef _NET_INETPEER_H +#define _NET_INETPEER_H + +#include +#include +#include +#include +#include + +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 */ diff -u --recursive --new-file v2.3.36/linux/include/net/ip.h linux/include/net/ip.h --- v2.3.36/linux/include/net/ip.h Tue Nov 23 22:42:21 1999 +++ linux/include/net/ip.h Thu Jan 6 11:43:46 2000 @@ -96,7 +96,6 @@ 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, @@ -179,6 +178,16 @@ return (sk->protinfo.af_inet.pmtudisc == IP_PMTUDISC_DO || (sk->protinfo.af_inet.pmtudisc == IP_PMTUDISC_WANT && !(dst->mxlock&(1<frag_off&__constant_htons(IP_DF)) + iph->id = 0; + else + __ip_select_ident(iph, dst); } /* diff -u --recursive --new-file v2.3.36/linux/include/net/route.h linux/include/net/route.h --- v2.3.36/linux/include/net/route.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/route.h Thu Jan 6 11:43:38 2000 @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -53,6 +54,7 @@ __u8 scope; }; +struct inet_peer; struct rtable { union @@ -76,6 +78,7 @@ /* 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; @@ -136,6 +139,17 @@ ip_rt_put(*rp); *rp = NULL; 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 */ diff -u --recursive --new-file v2.3.36/linux/init/main.c linux/init/main.c --- v2.3.36/linux/init/main.c Wed Dec 29 13:13:21 1999 +++ linux/init/main.c Thu Jan 6 10:14:36 2000 @@ -509,6 +509,7 @@ page_cache_init(mempages); kiobuf_init(); signals_init(); + bdev_init(); inode_init(); file_table_init(); #if defined(CONFIG_SYSVIPC) diff -u --recursive --new-file v2.3.36/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.3.36/linux/kernel/ksyms.c Tue Jan 4 13:57:21 2000 +++ linux/kernel/ksyms.c Thu Jan 6 10:14:36 2000 @@ -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(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(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); diff -u --recursive --new-file v2.3.36/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.3.36/linux/mm/swapfile.c Tue Dec 14 01:27:24 1999 +++ linux/mm/swapfile.c Thu Jan 6 10:14:36 2000 @@ -444,7 +444,6 @@ { struct swap_info_struct * p = NULL; struct dentry * dentry; - struct file filp; int i, type, prev; int err = -EPERM; @@ -508,17 +507,8 @@ 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 @@ 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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.36/linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- v2.3.36/linux/net/ipv4/Config.in Mon Dec 20 18:48:22 1999 +++ linux/net/ipv4/Config.in Thu Jan 6 10:15:52 2000 @@ -8,7 +8,9 @@ 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 diff -u --recursive --new-file v2.3.36/linux/net/ipv4/Makefile linux/net/ipv4/Makefile --- v2.3.36/linux/net/ipv4/Makefile Thu Aug 26 13:05:45 1999 +++ linux/net/ipv4/Makefile Thu Jan 6 10:14:36 2000 @@ -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\ diff -u --recursive --new-file v2.3.36/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c --- v2.3.36/linux/net/ipv4/igmp.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/igmp.c Thu Jan 6 10:14:36 2000 @@ -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 @@ -224,13 +224,13 @@ 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 -u --recursive --new-file v2.3.36/linux/net/ipv4/inetpeer.c linux/net/ipv4/inetpeer.c --- v2.3.36/linux/net/ipv4/inetpeer.c Wed Dec 31 16:00:00 1969 +++ linux/net/ipv4/inetpeer.c Thu Jan 6 10:14:36 2000 @@ -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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 + * . 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); +} diff -u --recursive --new-file v2.3.36/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c --- v2.3.36/linux/net/ipv4/ip_gre.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv4/ip_gre.c Thu Jan 6 10:14:36 2000 @@ -815,7 +815,7 @@ } 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; diff -u --recursive --new-file v2.3.36/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c --- v2.3.36/linux/net/ipv4/ip_output.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/ip_output.c Thu Jan 6 10:14:36 2000 @@ -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, * Fred N. van Kempen, @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -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 @@ { 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 @@ 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 @@ 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 @@ kfree_skb(skb); return -EMSGSIZE; } + ip_select_ident(iph, &rt->u.dst); return ip_fragment(skb, skb->dst->output); } @@ -429,7 +431,6 @@ } 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 @@ 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 @@ 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 @@ 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 @@ /* * 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,14 +528,14 @@ /* * 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; } @@ -542,15 +543,9 @@ 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 @@ /* * 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 @@ /* * 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ kfree_skb(skb); ip_statistics.IpFragOKs++; return err; - + fail: kfree_skb(skb); ip_statistics.IpFragFails++; @@ -1006,7 +1007,6 @@ NULL, }; - /* * IP registers the packet type and then calls the subprotocol initialisers */ @@ -1016,9 +1016,9 @@ dev_add_pack(&ip_packet_type); ip_rt_init(); + inet_initpeers(); #ifdef CONFIG_IP_MULTICAST proc_net_create("igmp", 0, ip_mc_procinfo); #endif } - diff -u --recursive --new-file v2.3.36/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c --- v2.3.36/linux/net/ipv4/ipip.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv4/ipip.c Thu Jan 6 10:14:36 2000 @@ -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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v2.3.36/linux/net/ipv4/ipmr.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/ipmr.c Thu Jan 6 10:14:36 2000 @@ -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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/net/ipv4/raw.c linux/net/ipv4/raw.c --- v2.3.36/linux/net/ipv4/raw.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/raw.c Thu Jan 6 10:14:36 2000 @@ -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, * Fred N. van Kempen, @@ -257,6 +257,7 @@ { struct iovec *iov; u32 saddr; + struct dst_entry *dst; }; /* @@ -296,7 +297,7 @@ * 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 @@ 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, diff -u --recursive --new-file v2.3.36/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.3.36/linux/net/ipv4/route.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/route.c Thu Jan 6 10:14:36 2000 @@ -83,9 +83,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -134,6 +136,7 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 diff -u --recursive --new-file v2.3.36/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- v2.3.36/linux/net/ipv4/sysctl_net_ipv4.c Fri Sep 10 23:57:38 1999 +++ linux/net/ipv4/sysctl_net_ipv4.c Thu Jan 6 10:14:36 2000 @@ -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 @@ /* 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 @@ {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} }; diff -u --recursive --new-file v2.3.36/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.3.36/linux/net/ipv4/tcp_ipv4.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/tcp_ipv4.c Thu Jan 6 10:14:36 2000 @@ -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 @@ 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); } diff -u --recursive --new-file v2.3.36/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c --- v2.3.36/linux/net/ipv6/ip6_output.c Thu Aug 26 13:05:46 1999 +++ linux/net/ipv6/ip6_output.c Thu Jan 6 10:14:36 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 * @@ -45,7 +45,17 @@ #include #include -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 @@ fhdr->reserved = 0; fhdr->frag_off = htons(offset); - fhdr->identification = ipv6_fragmentation_id++; + ipv6_select_ident(skb, fhdr); return &fhdr->nexthdr; } diff -u --recursive --new-file v2.3.36/linux/net/ipv6/route.c linux/net/ipv6/route.c --- v2.3.36/linux/net/ipv6/route.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv6/route.c Thu Jan 6 10:14:36 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/net/ipv6/sit.c linux/net/ipv6/sit.c --- v2.3.36/linux/net/ipv6/sit.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv6/sit.c Thu Jan 6 10:14:36 2000 @@ -6,7 +6,7 @@ * Pedro Roque * Alexey Kuznetsov * - * $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 @@ 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; diff -u --recursive --new-file v2.3.36/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.3.36/linux/net/ipv6/tcp_ipv6.c Tue Jan 4 13:57:21 2000 +++ linux/net/ipv6/tcp_ipv6.c Thu Jan 6 10:14:36 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 __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 @@ */ 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) diff -u --recursive --new-file v2.3.36/linux/net/netsyms.c linux/net/netsyms.c --- v2.3.36/linux/net/netsyms.c Tue Jan 4 13:57:21 2000 +++ linux/net/netsyms.c Thu Jan 6 10:14:36 2000 @@ -28,6 +28,7 @@ #endif #include #include +#include #ifdef CONFIG_BRIDGE #include @@ -235,7 +236,7 @@ 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 @@ #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