]> git.hungrycats.org Git - linux/commitdiff
v2.5.1.6 -> v2.5.1.7
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 07:59:51 +0000 (23:59 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 07:59:51 +0000 (23:59 -0800)
- Jeff Garzik: fix up loop and md for struct kdev_t typechecking
- Jeff Garzik: improved old-tulip network driver
- Arnaldo: more scsi driver bio updates
- Kai Germaschewski: ISDN updates
- various: kdev_t updates

154 files changed:
Documentation/Configure.help
Documentation/usb/ehci.txt [new file with mode: 0644]
Documentation/usb/stv680.txt [new file with mode: 0644]
Documentation/usb/usb-serial.txt
Makefile
arch/i386/kernel/cpuid.c
arch/i386/kernel/msr.c
drivers/block/DAC960.h
drivers/block/cciss.c
drivers/block/cciss_cmd.h
drivers/block/cpqarray.c
drivers/block/elevator.c
drivers/block/ll_rw_blk.c
drivers/block/loop.c
drivers/block/rd.c
drivers/cdrom/sonycd535.c
drivers/char/acquirewdt.c
drivers/char/advantechwdt.c
drivers/char/busmouse.c
drivers/char/eurotechwdt.c
drivers/char/ib700wdt.c
drivers/char/joystick/serport.c
drivers/char/lp.c
drivers/char/machzwd.c
drivers/char/pcwd.c
drivers/char/ppdev.c
drivers/char/sysrq.c
drivers/char/tty_io.c
drivers/char/wdt.c
drivers/char/wdt_pci.c
drivers/i2c/i2c-dev.c
drivers/ide/ide-disk.c
drivers/ide/ide-probe.c
drivers/ide/ide.c
drivers/ide/pdc4030.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/mousedev.c
drivers/isdn/Config.in
drivers/isdn/avmb1/avmcard.h
drivers/isdn/avmb1/b1.c
drivers/isdn/avmb1/b1dma.c
drivers/isdn/avmb1/b1pci.c
drivers/isdn/avmb1/c4.c
drivers/isdn/avmb1/capi.c
drivers/isdn/avmb1/capifs.c
drivers/isdn/avmb1/t1pci.c
drivers/isdn/hisax/Makefile
drivers/isdn/hisax/config.c
drivers/isdn/hisax/hisax.h
drivers/isdn/isdn_common.c
drivers/isdn/isdn_ppp.c
drivers/isdn/isdn_tty.c
drivers/media/video/cpia.c
drivers/media/video/videodev.c
drivers/net/de2104x.c
drivers/net/defxx.c
drivers/net/irda/irtty.c
drivers/net/slip.c
drivers/net/wan/cosa.c
drivers/net/wan/sdla_chdlc.c
drivers/scsi/BusLogic.h
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aha1740.c
drivers/scsi/dpt_i2o.c
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/fdomain.c
drivers/scsi/ide-scsi.c
drivers/scsi/in2000.c
drivers/scsi/in2000.h
drivers/scsi/ips.c
drivers/scsi/pci2000.c
drivers/scsi/pci2220i.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/scsi/sim710.c
drivers/scsi/sr.c
drivers/scsi/sr_ioctl.c
drivers/scsi/sr_vendor.c
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
drivers/sound/cs4281/cs4281m.c
drivers/sound/cs46xx.c
drivers/sound/es1370.c
drivers/sound/esssolo1.c
drivers/sound/i810_audio.c
drivers/sound/maestro.c
drivers/sound/maestro3.c
drivers/sound/soundcard.c
drivers/usb/Config.in
drivers/usb/Makefile
drivers/usb/acm.c
drivers/usb/audio.c
drivers/usb/bluetooth.c
drivers/usb/dabusb.c
drivers/usb/dc2xx.c
drivers/usb/hcd/Config.in
drivers/usb/hiddev.c
drivers/usb/printer.c
drivers/usb/scanner.c
drivers/usb/scanner.h
drivers/usb/serial/Config.in
drivers/usb/serial/Makefile
drivers/usb/serial/usbserial.c
drivers/usb/stv680.c [new file with mode: 0644]
drivers/usb/stv680.h [new file with mode: 0644]
drivers/usb/vicam.c [new file with mode: 0644]
drivers/usb/vicam.h [new file with mode: 0644]
drivers/usb/vicamurbs.h [new file with mode: 0644]
drivers/video/fbcon.c
drivers/video/fbmem.c
drivers/video/vesafb.c
fs/affs/super.c
fs/coda/inode.c
fs/cramfs/inode.c
fs/devfs/base.c
fs/devfs/util.c
fs/dquot.c
fs/ext3/ialloc.c
fs/ext3/super.c
fs/hfs/file.c
fs/intermezzo/psdev.c
fs/intermezzo/super.c
fs/jffs/inode-v23.c
fs/jffs2/dir.c
fs/jffs2/file.c
fs/jffs2/gc.c
fs/jffs2/super.c
fs/namei.c
fs/ncpfs/inode.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/partitions/acorn.c
fs/partitions/ibm.c
fs/romfs/inode.c
fs/smbfs/ChangeLog
fs/smbfs/file.c
fs/smbfs/getopt.c
fs/smbfs/getopt.h
fs/smbfs/inode.c
fs/umsdos/inode.c
include/linux/blk.h
include/linux/blkdev.h
include/linux/elevator.h
include/linux/ide.h
include/linux/sched.h
kernel/device.c
kernel/sched.c
net/irda/ircomm/ircomm_tty.c
net/netlink/netlink_dev.c

index bd149af36fa058789c37a99da3ace3cfd654553d..82f8b7d9660b081dabac0b679398df3e1cd3e354 100644 (file)
@@ -12541,6 +12541,30 @@ CONFIG_USB_LONG_TIMEOUT
   If you have an MGE Ellipse UPS, or you see timeouts in HID
   transactions, say Y; otherwise say N.
 
+EHCI (USB 2.0) support
+CONFIG_USB_EHCI_HCD
+  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
+  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
+  If your USB host controller supports USB 2.0, you will likely want to
+  configure this Host Controller Driver.  At this writing, the primary
+  implementation of EHCI is a chip from NEC, widely available in add-on
+  PCI cards, but implementations are in the works from other vendors
+  including Intel and Philips.  Motherboard support is appearing.
+
+  EHCI controllers are packaged with "companion" host controllers (OHCI
+  or UHCI) to handle USB 1.1 devices connected to root hub ports.  Ports
+  will connect to EHCI if it the device is high speed, otherwise they
+  connect to a companion controller.  If you configure EHCI, you should
+  probably configure the OHCI (for NEC and some other vendors) USB Host
+  Controller Driver too.
+
+  You may want to read <file:Documentation/usb/ehci.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ehci-hcd.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 UHCI (Intel PIIX4, VIA, ...) support
 CONFIG_USB_UHCI
   The Universal Host Controller Interface is a standard by Intel for
@@ -12841,6 +12865,17 @@ CONFIG_USB_SERIAL_VISOR
   The module will be called visor.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB Compaq iPAQ Driver
+CONFIG_USB_SERIAL_IPAQ
+  Say Y here if you want to connect to your Compaq iPAQ running
+  Windows CE 3.0 using a USB autosync cable. For information on using
+  the driver, read <file:Documentation/usb/usb-serial.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ipaq.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 USB IR Dongle Serial Driver
 CONFIG_USB_SERIAL_IR
   Say Y here if you want to enable simple serial support for USB IrDA
@@ -13061,6 +13096,22 @@ CONFIG_USB_SERIAL_EDGEPORT
   The module will be called io_edgeport.o.  If you want to compile it
   as a module, say M here and read <file:Documentation/modules.txt>.
 
+USB PalmConnect (and other KL5KUSB105-based) Single Port Serial Driver
+CONFIG_USB_SERIAL_KLSI
+  Say Y here if you want to use a KL5KUSB105 - based single port
+  serial adapter. The most widely known -- and currently the only
+  tested -- device in this category is the PalmConnect USB Serial
+  adapter sold by Palm Inc. for use with their Palm III and Palm V
+  series PDAs.
+
+  Please read <file:Documentation/usb/usb-serial.txt> for more
+  information.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called kl5kusb105.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
 USB Serial Converter verbose debug
 CONFIG_USB_SERIAL_DEBUG
   Say Y here if you want verbose debug messages from the USB Serial
@@ -13167,6 +13218,54 @@ CONFIG_USB_PWC
   The module will be called pwc.o.  If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB SE401 Camera support
+CONFIG_USB_SE401
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. See <file:Documentation/usb/se401.txt> for more
+  information and for a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called se401.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+USB STV680 (Pencam) Camera support
+CONFIG_USB_STV680
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. This includes the Pencam line of cameras.
+  See <file:Documentation/usb/stv680.txt> for more information and for
+  a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called stv680.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+Vicam
+CONFIG_USB_VICAM
+  Say Y here if you have 3com homeconnect camera (vicam).
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called vicam.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+
 Pegasus/Pegasus II based USB-Ethernet device support
 CONFIG_USB_PEGASUS
   Say Y here if you know you have Pegasus or Pegasus II based adapter.
@@ -16961,22 +17060,6 @@ CONFIG_PM
   will issue the hlt instruction if nothing is to be done, thereby
   sending the processor to sleep and saving power.
 
-USB SE401 Camera support
-CONFIG_USB_SE401
-  Say Y here if you want to connect this type of camera to your
-  computer's USB port. See <file:Documentation/usb/se401.txt> for more
-  information and for a list of supported cameras.
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Multimedia Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called se401.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
 ACPI support
 CONFIG_ACPI
   ACPI/OSPM support for Linux is currently under development. As such,
diff --git a/Documentation/usb/ehci.txt b/Documentation/usb/ehci.txt
new file mode 100644 (file)
index 0000000..205d412
--- /dev/null
@@ -0,0 +1,164 @@
+18-Dec-2001
+
+The EHCI driver is used to talk to high speed USB 2.0 devices using
+USB 2.0-capable host controller hardware.  The USB 2.0 standard is
+compatible with the USB 1.1 standard. It defines three transfer speeds:
+
+    - "High Speed" 480 Mbit/sec (60 MByte/sec)
+    - "Full Speed" 12 Mbit/sec (1.5 MByte/sec)
+    - "Low Speed" 1.5 Mbit/sec
+
+USB 1.1 only addressed full speed and low speed.  High speed devices
+can be used on USB 1.1 systems, but they slow down to USB 1.1 speeds. 
+
+USB 1.1 devices may also be used on USB 2.0 systems.  When plugged
+into an EHCI controller, they are given to a USB 1.1 "companion"
+controller, which is a OHCI or UHCI controller as normally used with
+such devices.  When USB 1.1 devices plug into USB 2.0 hubs, they
+interact with the EHCI controller through a "Transaction Translator"
+(TT) in the hub, which turns low or full speed transactions into
+high speed "split transactions" that don't waste transfer bandwidth.
+
+At this writing, high speed devices are finally beginning to appear.
+While usb-storage devices have been available for some time (working
+quite speedily on the 2.4 version of this driver), hubs have only
+very recently become available.
+
+Note that USB 2.0 support involves more than just EHCI.  It requires
+other changes to the Linux-USB core APIs, including the hub driver,
+but those changes haven't needed to really change the basic "usbcore"
+APIs exposed to USB device drivers.
+
+- David Brownell
+  <dbrownell@users.sourceforge.net>
+
+
+FUNCTIONALITY
+
+This driver is regularly tested on x86 hardware, and has also been
+used on PPC hardware so big/little endianneess issues should be gone.
+It's believed to do all the right PCI magic so that I/O works even on
+systems with interesting DMA mapping issues.
+
+At this writing the driver should comfortably handle all control and bulk
+transfers, including requests to USB 1.1 devices through transaction
+translators (TTs) in USB 2.0 hubs.  However, there some situations where
+the hub driver needs to clear TT error state, which it doesn't yet do.
+
+Interrupt transfer support is newly functional and not yet as robust as
+control and bulk traffic.  As yet there is no support for split transaction
+scheduling for interrupt transfers, which means among other things that
+connecting USB 1.1 hubs, keyboards, and mice to USB 2.0 hubs won't work.
+Connect them to USB 1.1 hubs, or to a root hub.
+
+Isochronous (ISO) transfer support is not yet working.  No production
+high speed devices are available which would need it (though high quality
+webcams are in the works!).  Note that split transaction support for ISO
+transfers can't share much code with the code for high speed ISO transfers,
+since EHCI represents these with a different data structure.
+
+The EHCI root hub code should hand off USB 1.1 devices to its companion
+controller.  This driver doesn't need to know anything about those
+drivers; a OHCI or UHCI driver that works already doesn't need to change
+just because the EHCI driver is also present.
+
+There are some issues with power management; suspend/resume doesn't
+behave quite right at the moment.
+
+
+USE BY
+
+Assuming you have an EHCI controller (on a PCI card or motherboard)
+and have compiled this driver as a module, load this like:
+
+    # modprobe ehci-hcd
+
+and remove it by:
+
+    # rmmod ehci-hcd
+
+You should also have a driver for a "companion controller", such as
+"ohci-hcd", "usb-ohci", "usb-uhci", or "uhci".  In case of any trouble
+with the EHCI driver, remove its module and then the driver for that
+companion controller will take over (at lower speed) all the devices
+that were previously handled by the EHCI driver.
+
+Module parameters (pass to "modprobe") include:
+
+    log2_irq_thresh (default 0):
+       Log2 of default interrupt delay, in microframes.  The default
+       value is 0, indicating 1 microframe (125 usec).  Maximum value
+       is 6, indicating 2^6 = 64 microframes.  This controls how often
+       the EHCI controller can issue interrupts.
+
+The EHCI interrupt handler just acknowledges interrupts and schedules
+a tasklet to handle whatever needs handling.  That keeps latencies low,
+no matter how often interrupts are issued.
+
+Device drivers shouldn't care whether they're running over EHCI or not,
+but they may want to check for "usb_device->speed == USB_SPEED_HIGH".
+High speed devices can do things that full speed (or low speed) ones
+can't, such as "high bandwidth" periodic (interrupt or ISO) transfers.
+
+
+PERFORMANCE
+
+USB 2.0 throughput is gated by two main factors:  how fast the host
+controller can process requests, and how fast devices can respond to
+them.  The 480 Mbit/sec "raw transfer rate" is obeyed by all devices,
+but aggregate throughput is also affected by issues like delays between
+individual high speed packets, driver intelligence, and of course the
+overall system load.  Latency is also a performance concern.
+
+Bulk transfers are most often used where throughput is an issue.  It's
+good to keep in mind that bulk transfers are always in 512 byte packets,
+and at most 13 of those fit into one USB 2.0 microframe.  Eight USB 2.0
+microframes fit in a USB 1.1 frame; a microframe is 1 msec/8 = 125 usec.
+
+Hardware Performance
+
+At this writing, individual USB 2.0 devices tend to max out at around
+20 MByte/sec transfer rates.  This is of course subject to change;
+and some devices now go faster, while others go slower.
+
+The NEC implementation of EHCI seems to have a hardware bottleneck
+at around 28 MByte/sec aggregate transfer rate.  While this is clearly
+enough for a single device at 20 MByte/sec, putting three such devices
+onto one bus does not get you 60 MByte/sec.  The issue appears to be
+that the controller hardware won't do concurrent USB and PCI access,
+so that it's only trying six (or maybe seven) USB transactions each
+microframe rather than thirteen.  (Seems like a reasonable trade off
+for a product that beat all the others to market by over a year!)
+It's expected that newer implementations will better this, throwing
+more silicon real estate at the problem so that new motherboard chip
+sets will get closer to that 60 MByte/sec target.
+
+There's a minimum latency of one microframe (125 usec) for the host
+to receive interrupts from the EHCI controller indicating completion
+of requests.  That latency is tunable; there's a module option.  By
+default ehci-hcd driver uses the minimum latency, which means that if
+you issue a control or bulk request you can often expect to learn that
+it completed in less than 250 usec (depending on transfer size).
+
+Software Performance
+
+To get even 20 MByte/sec transfer rates, Linux-USB device drivers will
+need to keep the EHCI queue full.  That means issuing large requests,
+or using bulk queuing if a series of small requests needs to be issued.
+When drivers don't do that, their performance results will show it.
+
+In typical situations, a usb_bulk_msg() loop writing out 4 KB chunks is
+going to waste more than half the USB 2.0 bandwidth.  Delays between the
+I/O completion and the driver issuing the next request will take longer
+than the I/O.  If that same loop used 16 KB chunks, it'd be better; a
+sequence of 128 KB chunks would waste a lot less.
+
+But rather than depending on such large I/O buffers to make synchronous
+I/O be efficient, it's better to just queue all several (bulk) requests
+to the HC, and wait for them all to complete (or be canceled on error).
+Such URB queuing should work with all the USB 1.1 HC drivers too.
+
+TBD:  Interrupt and ISO transfer performance issues.  Those periodic
+transfers are fully scheduled, so the main issue is likely to be how
+to trigger "high bandwidth" modes.
+
diff --git a/Documentation/usb/stv680.txt b/Documentation/usb/stv680.txt
new file mode 100644 (file)
index 0000000..6448041
--- /dev/null
@@ -0,0 +1,55 @@
+Linux driver for STV0680 based USB cameras
+
+Copyright, 2001, Kevin Sisson
+
+
+INTRODUCTION:
+
+STMicroelectronics produces the STV0680B chip, which comes in two 
+types, -001 and -003. The -003 version allows the recording and downloading 
+of sound clips from the camera, and allows a flash attachment. Otherwise, 
+it uses the same commands as the -001 version. Both versions support a 
+variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20 
+CIF pictures. The STV0680 supports either a serial or a usb interface, and 
+video is possible through the usb interface.
+
+The following cameras are known to work with this driver, although any 
+camera with Vendor/Product codes of 0553/0202 should work:
+
+Aiptek Pencam (various models)
+Nisis QuickPix 2
+Radio Shack 'Kid's digital camera' (#60-1207)
+At least one Trust Spycam model
+Several other European brand models
+
+WHAT YOU NEED:
+
+-      USB support
+-      VIDEO4LINUX support
+
+More information about USB support for linux can be found at:
+http://www.linux-usb.org
+
+
+MODULE OPTIONS:
+
+When the driver is compiled as a module, you can set a "swapRGB=1"
+option, if necessary, for those applications that require it 
+(such as xawtv). However, the driver should detect and set this 
+automatically, so this option should not normally be used.
+
+
+KNOWN PROBLEMS:
+
+The driver seems to work better with the usb-ohci than the usb-uhci host 
+controller driver. 
+
+HELP:
+
+The latest info on this driver can be found at:
+http://personal.clt.bellsouth.net/~kjsisson or at
+http://stv0680-usb.sourceforge.net
+
+Any questions to me can be send to:  kjsisson@bellsouth.net
+
+
index a3b816d1a07b64379f23639bcaf1651a86eba02b..dbab7aa4ace1a43833bbd8bb645f16c1abd629f8 100644 (file)
@@ -95,6 +95,66 @@ HandSpring Visor, Palm USB, and Cli
   Kroah-Hartman at greg@kroah.com
 
 
+Compaq iPAQ driver
+
+  This driver can be used to connect to Compaq iPAQ PDAs running
+  Windows CE 3.0 using a USB autosync cable. It has been tested only on
+  the Compaq H3135. It should work with the H3600 and later models too.
+  It may work with other CE based handhelds as well.
+
+  The driver presents a serial interface (usually on /dev/ttyUSB0) over
+  which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
+  is done, you can transfer files, backup, download email etc. The most
+  significant advantage of using USB is speed - you can get 73 to 113
+  kbytes/sec for download/upload to the iPAQ.
+
+  The driver works intermittently with the usb-uhci driver but quite
+  reliably with the uhci driver. Make sure you have the right driver
+  loaded - usb-uhci is often the default.
+
+  You must setup hotplug to invoke pppd as soon as the iPAQ is connected.
+  A ppp script like the one below may be used:
+
+       #!/bin/bash
+
+       MYIP=linux.box.ip
+       REMOTEIP=ipaq.ip
+       MYDNS=my.dns.server
+       killall -9 pppd
+       /usr/sbin/pppd /dev/ttyUSB0 \
+       connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \
+       nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \
+       proxyarp
+
+  You must also download and install asyncd from http://synce.sourceforge.net
+  This is required to emulate keep-alive packets which are exchanged by
+  ActiveSync and the iPAQ.
+
+  On connecting the cable, you should see the usual "Device Connected",
+  "User Authenticated" messages flash by on your iPAQ. Once connected,
+  you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ
+  and other synce utilities from the Linux side. Remember to enable IP
+  forwarding. 
+
+  To use Pocket IE, follow the instructions given at
+  http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing
+  on Win98. Omit the proxy server part; Linux is quite capable of forwarding
+  packets unlike Win98. Another modification is required at least for the
+  iPAQ - disable autosync by going to the Start/Settings/Connections menu
+  and unchecking the "Automatically synchronize ..." box. Go to
+  Start/Programs/Connections, connect the cable and select "usbdial" (or
+  whatever you named your new USB connection). You should finally wind
+  up with a "Connected to usbdial" window with status shown as connected.
+  Now start up PIE and browse away.
+
+  If it doesn't work for some reason, load both the usbserial and ipaq module
+  with the module parameter "debug" set to 1 and examine the system log.
+  You can also try soft-resetting your iPAQ before attempting a connection.
+
+  For any questions or problems with the driver, please contact Ganesh
+  Varadarajan <ganesh@veritas.com>
+
+
 Keyspan PDA Serial Adapter
 
   Single port DB-9 serial adapter, pushed as a PDA adapter for iMacs (mostly
@@ -302,6 +362,32 @@ Prolific PL2303 Driver
   Kroah-Hartman at greg@kroah.com
   
 
+KL5KUSB105 chipset / PalmConnect USB single-port adapter
+  
+Current status:
+  The driver was put together by looking at the usb bus transactions
+  done by Palm's driver under Windows, so a lot of functionality is
+  still missing.  Notably, serial ioctls are sometimes faked or not yet
+  implemented.  Support for finding out about DSR and CTS line status is
+  however implemented (though not nicely), so your favorite autopilot(1)
+  and pilot-manager -daemon calls will work.  Baud rates up to 115200
+  are supported, but handshaking (software or hardware) is not, which is
+  why it is wise to cut down on the rate used is wise for large
+  transfers until this is settled.
+  
+Options supported:
+  If this driver is compiled as a module you can pass the following
+  options to it:
+  debug                        - extra verbose debugging info
+                         (default: 0; nonzero enables)
+  use_lowlatency       - use low_latency flag to speed up tty layer
+                         when reading from from the device.
+                         (default: 0; nonzero enables)
+
+  See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
+  information on this driver.
+
+
 Generic Serial driver
 
   If your device is not one of the above listed devices, compatible with
index ca461be4b83ced6f294cadd8cfa095198d9c44f1..35a9e12be6d8d28d0e0c362fdeba533c76452ccf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 2
-EXTRAVERSION =-pre6
+EXTRAVERSION =-pre7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 6fb3f91728f861ae84ad3f3daae89ab054cac8a7..2686bc9bcfd9e4784f3df9dea98b8420c4ab7d0b 100644 (file)
@@ -101,7 +101,7 @@ static ssize_t cpuid_read(struct file * file, char * buf,
   u32 data[4];
   size_t rv;
   u32 reg = *ppos;
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   
   if ( count % 16 )
     return -EINVAL; /* Invalid chunk size */
@@ -119,7 +119,7 @@ static ssize_t cpuid_read(struct file * file, char * buf,
 
 static int cpuid_open(struct inode *inode, struct file *file)
 {
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   struct cpuinfo_x86 *c = &(cpu_data)[cpu];
 
   if ( !(cpu_online_map & (1UL << cpu)) )
index feee5b67eaae5447d9e114d9bcc79df8855b250c..5445ca5ac47b51986f8ef61e79eac7b2357b7a9e 100644 (file)
@@ -181,7 +181,7 @@ static ssize_t msr_read(struct file * file, char * buf,
   u32 data[2];
   size_t rv;
   u32 reg = *ppos;
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   int err;
 
   if ( count % 8 )
@@ -206,7 +206,7 @@ static ssize_t msr_write(struct file * file, const char * buf,
   u32 data[2];
   size_t rv;
   u32 reg = *ppos;
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   int err;
 
   if ( count % 8 )
@@ -226,7 +226,7 @@ static ssize_t msr_write(struct file * file, const char * buf,
 
 static int msr_open(struct inode *inode, struct file *file)
 {
-  int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+  int cpu = minor(file->f_dentry->d_inode->i_rdev);
   struct cpuinfo_x86 *c = &(cpu_data)[cpu];
   
   if ( !(cpu_online_map & (1UL << cpu)) )
index 71e7db452720de3a1084df5327b057a4860d64c3..9826533648ebf4d3c7489f673eace2df5b7d4527 100644 (file)
@@ -2054,13 +2054,13 @@ extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument);
 */
 
 #define DAC960_ControllerNumber(Device) \
-  (MAJOR(Device) - DAC960_MAJOR)
+  (major(Device) - DAC960_MAJOR)
 
 #define DAC960_LogicalDriveNumber(Device) \
-  (MINOR(Device) >> DAC960_MaxPartitionsBits)
+  (minor(Device) >> DAC960_MaxPartitionsBits)
 
 #define DAC960_PartitionNumber(Device) \
-  (MINOR(Device) & (DAC960_MaxPartitions - 1))
+  (minor(Device) & (DAC960_MaxPartitions - 1))
 
 #define DAC960_MajorNumber(ControllerNumber) \
   (DAC960_MAJOR + (ControllerNumber))
index 7a5645e95b2dc020e222922d5f734abe1e9ae439..e2792736f08e6d84cbc3395096c289ea1e17aece 100644 (file)
@@ -317,8 +317,8 @@ static void cciss_geninit( int ctlr)
  */
 static int cciss_open(struct inode *inode, struct file *filep)
 {
-       int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-       int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+       int ctlr = major(inode->i_rdev) - MAJOR_NR;
+       int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 #ifdef CCISS_DEBUG
        printk(KERN_DEBUG "cciss_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
@@ -327,7 +327,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
        if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
                return -ENXIO;
 
-       if (!suser() && hba[ctlr]->sizes[ MINOR(inode->i_rdev)] == 0)
+       if (!suser() && hba[ctlr]->sizes[minor(inode->i_rdev)] == 0)
                return -ENXIO;
 
        /*
@@ -337,8 +337,8 @@ static int cciss_open(struct inode *inode, struct file *filep)
         * for "raw controller".
         */
        if (suser()
-               && (hba[ctlr]->sizes[MINOR(inode->i_rdev)] == 0) 
-               && (MINOR(inode->i_rdev)!= 0))
+               && (hba[ctlr]->sizes[minor(inode->i_rdev)] == 0) 
+               && (minor(inode->i_rdev)!= 0))
                return -ENXIO;
 
        hba[ctlr]->drv[dsk].usage_count++;
@@ -350,8 +350,8 @@ static int cciss_open(struct inode *inode, struct file *filep)
  */
 static int cciss_release(struct inode *inode, struct file *filep)
 {
-       int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-       int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+       int ctlr = major(inode->i_rdev) - MAJOR_NR;
+       int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 #ifdef CCISS_DEBUG
        printk(KERN_DEBUG "cciss_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
@@ -370,8 +370,8 @@ static int cciss_release(struct inode *inode, struct file *filep)
 static int cciss_ioctl(struct inode *inode, struct file *filep, 
                unsigned int cmd, unsigned long arg)
 {
-       int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-       int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+       int ctlr = major(inode->i_rdev) - MAJOR_NR;
+       int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
 #ifdef CCISS_DEBUG
        printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg);
@@ -696,8 +696,8 @@ static int revalidate_logvol(kdev_t dev, int maxusage)
         unsigned long flags;
         int res;
 
-        target = MINOR(dev) >> NWD_SHIFT;
-        ctlr = MAJOR(dev) - MAJOR_NR;
+        target = minor(dev) >> NWD_SHIFT;
+        ctlr = major(dev) - MAJOR_NR;
         gdev = &(hba[ctlr]->gendisk);
 
         spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
@@ -746,8 +746,8 @@ static int revalidate_allvol(kdev_t dev)
        int ctlr, i;
        unsigned long flags;
 
-       ctlr = MAJOR(dev) - MAJOR_NR;
-        if (MINOR(dev) != 0)
+       ctlr = major(dev) - MAJOR_NR;
+        if (minor(dev) != 0)
                 return -ENXIO;
 
         spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
@@ -781,9 +781,11 @@ static int revalidate_allvol(kdev_t dev)
         hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON);
 
         cciss_geninit(ctlr);
-        for(i=0; i<NWD; i++)
+        for(i=0; i<NWD; i++) {
+               kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
                 if (hba[ctlr]->sizes[ i<<NWD_SHIFT ])
-                        revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+                        revalidate_logvol(kdev, 2);
+       }
 
         hba[ctlr]->usage_count--;
         return 0;
@@ -1205,7 +1207,6 @@ static void do_cciss_request(request_queue_t *q)
        ctlr_info_t *h= q->queuedata; 
        CommandList_struct *c;
        int log_unit, start_blk, seg;
-       struct list_head *queue_head = &q->queue_head;
        struct request *creq;
        u64bit temp64;
        struct scatterlist tmp_sg[MAXSGENTRIES];
@@ -1215,17 +1216,17 @@ static void do_cciss_request(request_queue_t *q)
                goto startio;
 
 queue:
-       if (list_empty(queue_head))
+       if (blk_queue_empty(q))
                goto startio;
 
        creq = elv_next_request(q);
        if (creq->nr_phys_segments > MAXSGENTRIES)
                 BUG();
 
-        if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR )
+        if (h->ctlr != major(creq->rq_dev)-MAJOR_NR )
         {
                 printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
-                                h->ctlr, creq->rq_dev, creq);
+                                h->ctlr, major(creq->rq_dev), creq);
                 blkdev_dequeue_request(creq);
                 complete_buffers(creq->bio, 0);
                end_that_request_last(creq);
@@ -1243,7 +1244,7 @@ queue:
        c->rq = creq;
        
        /* fill in the request */ 
-       log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT; 
+       log_unit = minor(creq->rq_dev) >> NWD_SHIFT; 
        c->Header.ReplyQueue = 0;  // unused in simple mode
        c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag
        c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
@@ -1896,7 +1897,7 @@ static int __init cciss_init_one(struct pci_dev *pdev,
        cciss_geninit(i);
        for(j=0; j<NWD; j++)
                register_disk(&(hba[i]->gendisk),
-                       MKDEV(MAJOR_NR+i, j <<4), 
+                       mk_kdev(MAJOR_NR+i, j <<4), 
                        MAX_PART, &cciss_fops, 
                        hba[i]->drv[j].nr_blocks);
 
index 544b047c50c2305422dd8dc3870c25692e19556c..7faf6f05ca90787749029b7d2c540d8063300820 100644 (file)
@@ -7,7 +7,7 @@
 
 //general boundary defintions
 #define SENSEINFOBYTES          32//note that this value may vary between host implementations
-#define MAXSGENTRIES            32
+#define MAXSGENTRIES            31
 #define MAXREPLYQS              256
 
 //Command Status value
index 3fc4d0abb6c8e5ef2f94de5a084c05a8826c6b03..6a92fa4f5e28f20c2c369590ac6a88b0ac389fac 100644 (file)
@@ -499,7 +499,7 @@ int __init cpqarray_init(void)
                ida_geninit(i);
                for(j=0; j<NWD; j++)    
                        register_disk(&ida_gendisk[i], 
-                               MKDEV(MAJOR_NR+i,j<<4),
+                               mk_kdev(MAJOR_NR+i,j<<4),
                                16, &ida_fops, hba[i]->drv[j].nr_blks);
 
        }
@@ -776,15 +776,15 @@ DBGINFO(
  */
 static int ida_open(struct inode *inode, struct file *filep)
 {
-       int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-       int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+       int ctlr = major(inode->i_rdev) - MAJOR_NR;
+       int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
        DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
        if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
                return -ENXIO;
 
        if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) +
-                                               MINOR(inode->i_rdev)] == 0)
+                                               minor(inode->i_rdev)] == 0)
                return -ENXIO;
 
        /*
@@ -794,8 +794,8 @@ static int ida_open(struct inode *inode, struct file *filep)
         * for "raw controller".
         */
        if (suser()
-               && ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0 
-               && MINOR(inode->i_rdev) != 0)
+               && ida_sizes[(ctlr << CTLR_SHIFT) + minor(inode->i_rdev)] == 0 
+               && minor(inode->i_rdev) != 0)
                return -ENXIO;
 
        hba[ctlr]->drv[dsk].usage_count++;
@@ -808,8 +808,8 @@ static int ida_open(struct inode *inode, struct file *filep)
  */
 static int ida_release(struct inode *inode, struct file *filep)
 {
-       int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-       int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+       int ctlr = major(inode->i_rdev) - MAJOR_NR;
+       int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
 
        DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
 
@@ -857,7 +857,6 @@ static void do_ida_request(request_queue_t *q)
 {
        ctlr_info_t *h = q->queuedata;
        cmdlist_t *c;
-       struct list_head * queue_head = &q->queue_head;
        struct request *creq;
        struct scatterlist tmp_sg[SG_MAX];
        int i, dir, seg;
@@ -866,17 +865,17 @@ static void do_ida_request(request_queue_t *q)
                goto startio;
 
 queue_next:
-       if (list_empty(queue_head))
+       if (blk_queue_empty(q))
                goto startio;
 
        creq = elv_next_request(q);
        if (creq->nr_phys_segments > SG_MAX)
                BUG();
 
-       if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
+       if (h->ctlr != major(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
        {
                printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
-                               h->ctlr, creq->rq_dev, creq);
+                               h->ctlr, minor(creq->rq_dev), creq);
                blkdev_dequeue_request(creq);
                complete_buffers(creq->bio, 0);
                end_that_request_last(creq);
@@ -891,7 +890,7 @@ queue_next:
        spin_unlock_irq(q->queue_lock);
 
        c->ctlr = h->ctlr;
-       c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
+       c->hdr.unit = minor(creq->rq_dev) >> NWD_SHIFT;
        c->hdr.size = sizeof(rblk_t) >> 2;
        c->size += sizeof(rblk_t);
 
@@ -1109,8 +1108,8 @@ static void ida_timer(unsigned long tdata)
  */
 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
 {
-       int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
-       int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+       int ctlr = major(inode->i_rdev) - MAJOR_NR;
+       int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
        int error;
        int diskinfo[4];
        struct hd_geometry *geo = (struct hd_geometry *)arg;
@@ -1492,8 +1491,8 @@ static int revalidate_allvol(kdev_t dev)
        int ctlr, i;
        unsigned long flags;
 
-       ctlr = MAJOR(dev) - MAJOR_NR;
-       if (MINOR(dev) != 0)
+       ctlr = major(dev) - MAJOR_NR;
+       if (minor(dev) != 0)
                return -ENXIO;
 
        spin_lock_irqsave(IDA_LOCK(ctlr), flags);
@@ -1526,9 +1525,11 @@ static int revalidate_allvol(kdev_t dev)
        hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
 
        ida_geninit(ctlr);
-       for(i=0; i<NWD; i++)
+       for(i=0; i<NWD; i++) {
+               kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
                if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
-                       revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+                       revalidate_logvol(kdev, 2);
+       }
 
        hba[ctlr]->usage_count--;
        return 0;
@@ -1543,7 +1544,7 @@ static int revalidate_logvol(kdev_t dev, int maxusage)
        int res;
 
        target = DEVICE_NR(dev);
-       ctlr = MAJOR(dev) - MAJOR_NR;
+       ctlr = major(dev) - MAJOR_NR;
        gdev = &ida_gendisk[ctlr];
        
        spin_lock_irqsave(IDA_LOCK(ctlr), flags);
index 2dfaf4ebce7e13f66609163a7ea9232370e915fc..8fcdc77fad1320795a6f73e5069493cd6976da61 100644 (file)
@@ -121,45 +121,54 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
 
 inline int elv_try_merge(struct request *__rq, struct bio *bio)
 {
-       unsigned int count = bio_sectors(bio);
        int ret = ELEVATOR_NO_MERGE;
 
        /*
         * we can merge and sequence is ok, check if it's possible
         */
        if (elv_rq_merge_ok(__rq, bio)) {
-               if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
+               if (__rq->sector + __rq->nr_sectors == bio->bi_sector)
                        ret = ELEVATOR_BACK_MERGE;
-               } else if (__rq->sector - count == bio->bi_sector) {
-                       __rq->elevator_sequence -= count;
+               else if (__rq->sector - bio_sectors(bio) == bio->bi_sector)
                        ret = ELEVATOR_FRONT_MERGE;
-               }
        }
 
        return ret;
 }
 
-int elevator_linus_merge(request_queue_t *q, struct request **req,
-                        struct bio *bio)
+inline int elv_try_last_merge(request_queue_t *q, struct request **req,
+                             struct bio *bio)
 {
-       struct list_head *entry;
-       struct request *__rq;
-       int ret;
+       int ret = ELEVATOR_NO_MERGE;
 
        /*
         * give a one-shot try to merging with the last touched
         * request
         */
        if (q->last_merge) {
-               __rq = list_entry_rq(q->last_merge);
+               struct request *__rq = list_entry_rq(q->last_merge);
                BUG_ON(__rq->flags & REQ_STARTED);
 
-               if ((ret = elv_try_merge(__rq, bio))) {
+               if ((ret = elv_try_merge(__rq, bio)))
                        *req = __rq;
-                       return ret;
-               }
        }
 
+       return ret;
+}
+
+/*
+ * elevator_linux starts here
+ */
+int elevator_linus_merge(request_queue_t *q, struct request **req,
+                        struct bio *bio)
+{
+       struct list_head *entry;
+       struct request *__rq;
+       int ret;
+
+       if ((ret = elv_try_last_merge(q, req, bio)))
+               return ret;
+
        entry = &q->queue_head;
        ret = ELEVATOR_NO_MERGE;
        while ((entry = entry->prev) != &q->queue_head) {
@@ -171,17 +180,19 @@ int elevator_linus_merge(request_queue_t *q, struct request **req,
                /*
                 * simply "aging" of requests in queue
                 */
-               if (__rq->elevator_sequence-- <= 0)
+               if (elv_linus_sequence(__rq)-- <= 0)
                        break;
                if (!(__rq->flags & REQ_CMD))
                        continue;
-               if (__rq->elevator_sequence < bio_sectors(bio))
+               if (elv_linus_sequence(__rq) < bio_sectors(bio))
                        break;
 
                if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head))
                        *req = __rq;
 
                if ((ret = elv_try_merge(__rq, bio))) {
+                       if (ret == ELEVATOR_FRONT_MERGE)
+                               elv_linus_sequence(__rq) -= bio_sectors(bio);
                        *req = __rq;
                        q->last_merge = &__rq->queuelist;
                        break;
@@ -204,19 +215,27 @@ void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int c
        while ((entry = entry->next) != &q->queue_head) {
                struct request *tmp;
                tmp = list_entry_rq(entry);
-               tmp->elevator_sequence -= count;
+               elv_linus_sequence(tmp) -= count;
        }
 }
 
 void elevator_linus_merge_req(struct request *req, struct request *next)
 {
-       if (next->elevator_sequence < req->elevator_sequence)
-               req->elevator_sequence = next->elevator_sequence;
+       if (elv_linus_sequence(next) < elv_linus_sequence(req))
+               elv_linus_sequence(req) = elv_linus_sequence(next);
 }
 
-void elv_add_request_fn(request_queue_t *q, struct request *rq,
-                              struct list_head *insert_here)
+void elevator_linus_add_request(request_queue_t *q, struct request *rq,
+                               struct list_head *insert_here)
 {
+       elevator_t *e = &q->elevator;
+       int lat = 0, *latency = e->elevator_data;
+
+       if (!(rq->flags & REQ_BARRIER))
+               lat = latency[rq_data_dir(rq)];
+
+       elv_linus_sequence(rq) = lat;
+
        list_add(&rq->queuelist, insert_here);
 
        /*
@@ -228,24 +247,29 @@ void elv_add_request_fn(request_queue_t *q, struct request *rq,
                q->last_merge = &rq->queuelist;
 }
 
-struct request *elv_next_request_fn(request_queue_t *q)
+int elevator_linus_init(request_queue_t *q, elevator_t *e)
 {
-       if (!blk_queue_empty(q))
-               return list_entry_rq(q->queue_head.next);
+       int *latency;
 
-       return NULL;
-}
+       latency = kmalloc(2 * sizeof(int), GFP_KERNEL);
+       if (!latency)
+               return -ENOMEM;
 
-int elv_linus_init(request_queue_t *q, elevator_t *e)
-{
+       latency[READ] = 8192;
+       latency[WRITE] = 16384;
+
+       e->elevator_data = latency;
        return 0;
 }
 
-void elv_linus_exit(request_queue_t *q, elevator_t *e)
+void elevator_linus_exit(request_queue_t *q, elevator_t *e)
 {
+       kfree(e->elevator_data);
 }
 
 /*
+ * elevator noop
+ *
  * See if we can find a request that this buffer can be coalesced with.
  */
 int elevator_noop_merge(request_queue_t *q, struct request **req,
@@ -255,15 +279,8 @@ int elevator_noop_merge(request_queue_t *q, struct request **req,
        struct request *__rq;
        int ret;
 
-       if (q->last_merge) {
-               __rq = list_entry_rq(q->last_merge);
-               BUG_ON(__rq->flags & REQ_STARTED);
-
-               if ((ret = elv_try_merge(__rq, bio))) {
-                       *req = __rq;
-                       return ret;
-               }
-       }
+       if ((ret = elv_try_last_merge(q, req, bio)))
+               return ret;
 
        while ((entry = entry->prev) != &q->queue_head) {
                __rq = list_entry_rq(entry);
@@ -284,10 +301,31 @@ int elevator_noop_merge(request_queue_t *q, struct request **req,
        return ELEVATOR_NO_MERGE;
 }
 
-void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
+void elevator_noop_add_request(request_queue_t *q, struct request *rq,
+                              struct list_head *insert_here)
+{
+       list_add_tail(&rq->queuelist, &q->queue_head);
+
+       /*
+        * new merges must not precede this barrier
+        */
+       if (rq->flags & REQ_BARRIER)
+               q->last_merge = NULL;
+       else if (!q->last_merge)
+               q->last_merge = &rq->queuelist;
+}
+
+struct request *elevator_noop_next_request(request_queue_t *q)
+{
+       if (!blk_queue_empty(q))
+               return list_entry_rq(q->queue_head.next);
 
-void elevator_noop_merge_req(struct request *req, struct request *next) {}
+       return NULL;
+}
 
+/*
+ * general block -> elevator interface starts here
+ */
 int elevator_init(request_queue_t *q, elevator_t *e, elevator_t type)
 {
        *e = type;
@@ -312,4 +350,77 @@ int elevator_global_init(void)
        return 0;
 }
 
+void elv_merge_cleanup(request_queue_t *q, struct request *rq,
+                      int nr_sectors)
+{
+       elevator_t *e = &q->elevator;
+
+       if (e->elevator_merge_cleanup_fn)
+               e->elevator_merge_cleanup_fn(q, rq, nr_sectors);
+}
+
+int elv_merge(request_queue_t *q, struct request **rq, struct bio *bio)
+{
+       elevator_t *e = &q->elevator;
+
+       if (e->elevator_merge_fn)
+               return e->elevator_merge_fn(q, rq, bio);
+
+       return ELEVATOR_NO_MERGE;
+}
+
+void elv_merge_requests(request_queue_t *q, struct request *rq,
+                            struct request *next)
+{
+       elevator_t *e = &q->elevator;
+
+       if (e->elevator_merge_req_fn)
+               e->elevator_merge_req_fn(rq, next);
+}
+
+/*
+ * add_request and next_request are required to be supported, naturally
+ */
+void __elv_add_request(request_queue_t *q, struct request *rq,
+                         struct list_head *insert_here)
+{
+       q->elevator.elevator_add_req_fn(q, rq, insert_here);
+}
+
+struct request *__elv_next_request(request_queue_t *q)
+{
+       return q->elevator.elevator_next_req_fn(q);
+}
+
+void elv_remove_request(request_queue_t *q, struct request *rq)
+{
+       elevator_t *e = &q->elevator;
+
+       if (e->elevator_remove_req_fn)
+               e->elevator_remove_req_fn(q, rq);
+}
+
+elevator_t elevator_linus = {
+       elevator_merge_fn:              elevator_linus_merge,
+       elevator_merge_cleanup_fn:      elevator_linus_merge_cleanup,
+       elevator_merge_req_fn:          elevator_linus_merge_req,
+       elevator_next_req_fn:           elevator_noop_next_request,
+       elevator_add_req_fn:            elevator_linus_add_request,
+       elevator_init_fn:               elevator_linus_init,
+       elevator_exit_fn:               elevator_linus_exit,
+};
+
+elevator_t elevator_noop = {
+       elevator_merge_fn:              elevator_noop_merge,
+       elevator_next_req_fn:           elevator_noop_next_request,
+       elevator_add_req_fn:            elevator_noop_add_request,
+};
+
 module_init(elevator_global_init);
+
+EXPORT_SYMBOL(elevator_linus);
+EXPORT_SYMBOL(elevator_noop);
+
+EXPORT_SYMBOL(__elv_add_request);
+EXPORT_SYMBOL(__elv_next_request);
+EXPORT_SYMBOL(elv_remove_request);
index 060ebae4e7f295f7949f198bd87eeb8e8ab80bc8..f98c41e49c017181d5c1bddc55201e221e9737e9 100644 (file)
@@ -530,8 +530,10 @@ static inline int ll_new_hw_segment(request_queue_t *q,
                                    struct bio *bio)
 {
        int nr_hw_segs = bio_hw_segments(q, bio);
+       int nr_phys_segs = bio_phys_segments(q, bio);
 
-       if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments) {
+       if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments
+           || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
                req->flags |= REQ_NOMERGE;
                q->last_merge = NULL;
                return 0;
@@ -542,7 +544,7 @@ static inline int ll_new_hw_segment(request_queue_t *q,
         * counters.
         */
        req->nr_hw_segments += nr_hw_segs;
-       req->nr_phys_segments += bio_phys_segments(q, bio);
+       req->nr_phys_segments += nr_phys_segs;
        return 1;
 }
 
@@ -801,7 +803,7 @@ int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
        if (blk_init_free_list(q))
                return -ENOMEM;
 
-       if ((ret = elevator_init(q, &q->elevator, ELEVATOR_LINUS))) {
+       if ((ret = elevator_init(q, &q->elevator, elevator_linus))) {
                blk_cleanup_queue(q);
                return ret;
        }
@@ -822,6 +824,9 @@ int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
 
        blk_queue_make_request(q, __make_request);
        blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
+
+       blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
+       blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
        return 0;
 }
 
@@ -968,7 +973,7 @@ static inline void add_request(request_queue_t * q, struct request * req,
         * elevator indicated where it wants this request to be
         * inserted at elevator_merge time
         */
-       q->elevator.elevator_add_req_fn(q, req, insert_here);
+       __elv_add_request(q, req, insert_here);
 }
 
 /*
@@ -1028,7 +1033,7 @@ static void attempt_merge(request_queue_t *q, struct request *req,
         * counts here.
         */
        if (q->merge_requests_fn(q, req, next)) {
-               q->elevator.elevator_merge_req_fn(req, next);
+               elv_merge_requests(q, req, next);
 
                blkdev_dequeue_request(next);
 
@@ -1082,9 +1087,8 @@ void blk_attempt_remerge(request_queue_t *q, struct request *rq)
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
        struct request *req, *freereq = NULL;
-       int el_ret, latency = 0, rw, nr_sectors, cur_nr_sectors, barrier;
+       int el_ret, rw, nr_sectors, cur_nr_sectors, barrier;
        struct list_head *insert_here;
-       elevator_t *elevator = &q->elevator;
        sector_t sector;
 
        sector = bio->bi_sector;
@@ -1101,7 +1105,6 @@ static int __make_request(request_queue_t *q, struct bio *bio)
 
        spin_lock_prefetch(q->queue_lock);
 
-       latency = elevator_request_latency(elevator, rw);
        barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
 
        spin_lock_irq(q->queue_lock);
@@ -1114,14 +1117,14 @@ again:
                goto get_rq;
        }
 
-       el_ret = elevator->elevator_merge_fn(q, &req, bio);
+       el_ret = elv_merge(q, &req, bio);
        switch (el_ret) {
                case ELEVATOR_BACK_MERGE:
                        BUG_ON(!rq_mergeable(req));
                        if (!q->back_merge_fn(q, req, bio))
                                break;
 
-                       elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+                       elv_merge_cleanup(q, req, nr_sectors);
 
                        req->biotail->bi_next = bio;
                        req->biotail = bio;
@@ -1135,7 +1138,7 @@ again:
                        if (!q->front_merge_fn(q, req, bio))
                                break;
 
-                       elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+                       elv_merge_cleanup(q, req, nr_sectors);
 
                        bio->bi_next = req->bio;
                        req->bio = bio;
@@ -1196,11 +1199,6 @@ get_rq:
                goto again;
        }
 
-       /*
-        * fill up the request-info, and add it to the queue
-        */
-       req->elevator_sequence = latency;
-
        /*
         * first three bits are identical in rq->flags and bio->bi_rw,
         * see bio.h and blkdev.h
index 73065f0735b53a398153f5182c5298125e4adf90..2ef6fc465562e073377d47a8e9b11a5d5378d864 100644 (file)
@@ -155,8 +155,8 @@ static unsigned long compute_loop_size(struct loop_device *lo, struct dentry * l
 {
        if (S_ISREG(lo_dentry->d_inode->i_mode))
                return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS;
-       if (blk_size[MAJOR(lodev)])
-               return blk_size[MAJOR(lodev)][MINOR(lodev)] -
+       if (blk_size[major(lodev)])
+               return blk_size[major(lodev)][minor(lodev)] -
                                 (lo->lo_offset >> BLOCK_SIZE_BITS);
        return MAX_DISK_SIZE;
 }
@@ -379,12 +379,11 @@ static struct bio *loop_get_bio(struct loop_device *lo)
  */
 static int loop_end_io_transfer(struct bio *bio, int nr_sectors)
 {
-       struct loop_device *lo = &loop_dev[MINOR(bio->bi_dev)];
+       struct bio *rbh = bio->bi_private;
+       struct loop_device *lo = &loop_dev[minor(rbh->bi_dev)];
        int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 
        if (!uptodate || bio_rw(bio) == WRITE) {
-               struct bio *rbh = bio->bi_private;
-
                bio_endio(rbh, uptodate, nr_sectors);
                if (atomic_dec_and_test(&lo->lo_pending))
                        up(&lo->lo_bh_mutex);
@@ -429,10 +428,10 @@ static int loop_make_request(request_queue_t *q, struct bio *rbh)
        unsigned long IV;
        int rw = bio_rw(rbh);
 
-       if (MINOR(rbh->bi_dev) >= max_loop)
+       if (minor(rbh->bi_dev) >= max_loop)
                goto out;
 
-       lo = &loop_dev[MINOR(rbh->bi_dev)];
+       lo = &loop_dev[minor(rbh->bi_dev)];
        spin_lock_irq(&lo->lo_lock);
        if (lo->lo_state != Lo_bound)
                goto inactive;
@@ -615,7 +614,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, kdev_t dev,
 
        if (S_ISBLK(inode->i_mode)) {
                lo_device = inode->i_rdev;
-               if (lo_device == dev) {
+               if (kdev_same(lo_device, dev)) {
                        error = -EBUSY;
                        goto out;
                }
@@ -725,7 +724,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        loop_release_xfer(lo);
        lo->transfer = NULL;
        lo->ioctl = NULL;
-       lo->lo_device = 0;
+       lo->lo_device = NODEV;
        lo->lo_encrypt_type = 0;
        lo->lo_offset = 0;
        lo->lo_encrypt_key_size = 0;
@@ -818,12 +817,12 @@ static int lo_ioctl(struct inode * inode, struct file * file,
 
        if (!inode)
                return -EINVAL;
-       if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+       if (major(inode->i_rdev) != MAJOR_NR) {
                printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n",
                       MAJOR_NR);
                return -ENODEV;
        }
-       dev = MINOR(inode->i_rdev);
+       dev = minor(inode->i_rdev);
        if (dev >= max_loop)
                return -ENODEV;
        lo = &loop_dev[dev];
@@ -873,11 +872,11 @@ static int lo_open(struct inode *inode, struct file *file)
 
        if (!inode)
                return -EINVAL;
-       if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+       if (major(inode->i_rdev) != MAJOR_NR) {
                printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR);
                return -ENODEV;
        }
-       dev = MINOR(inode->i_rdev);
+       dev = minor(inode->i_rdev);
        if (dev >= max_loop)
                return -ENODEV;
 
@@ -900,12 +899,12 @@ static int lo_release(struct inode *inode, struct file *file)
 
        if (!inode)
                return 0;
-       if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+       if (major(inode->i_rdev) != MAJOR_NR) {
                printk(KERN_WARNING "lo_release: pseudo-major != %d\n",
                       MAJOR_NR);
                return 0;
        }
-       dev = MINOR(inode->i_rdev);
+       dev = minor(inode->i_rdev);
        if (dev >= max_loop)
                return 0;
 
@@ -1016,7 +1015,7 @@ int __init loop_init(void)
        blk_size[MAJOR_NR] = loop_sizes;
        blksize_size[MAJOR_NR] = loop_blksizes;
        for (i = 0; i < max_loop; i++)
-               register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &lo_fops, 0);
+               register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &lo_fops, 0);
 
        printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
        return 0;
index 13f2351f420fd0eefbcade7bd760f810557881cc..25f0ebe2fc4fdfdd6f7d3ae186ca28c1bcd33ba5 100644 (file)
@@ -246,7 +246,7 @@ static int rd_make_request(request_queue_t * q, struct bio *sbh)
        unsigned long offset, len;
        int rw = sbh->bi_rw;
 
-       minor = MINOR(sbh->bi_dev);
+       minor = minor(sbh->bi_dev);
 
        if (minor >= NUM_RAMDISKS)
                goto fail;
@@ -280,10 +280,10 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        int error = -EINVAL;
        unsigned int minor;
 
-       if (!inode || !inode->i_rdev)   
+       if (!inode || kdev_none(inode->i_rdev))
                goto out;
 
-       minor = MINOR(inode->i_rdev);
+       minor = minor(inode->i_rdev);
 
        switch (cmd) {
                case BLKFLSBUF:
@@ -407,7 +407,7 @@ static void __exit rd_cleanup (void)
                rd_bdev[i] = NULL;
                if (bdev)
                        blkdev_put(bdev, BDEV_FILE);
-               destroy_buffers(MKDEV(MAJOR_NR, i));
+               destroy_buffers(mk_kdev(MAJOR_NR, i));
        }
 
        devfs_unregister (devfs_handle);
@@ -449,7 +449,7 @@ static int __init rd_init (void)
                               &rd_bd_op, NULL);
 
        for (i = 0; i < NUM_RAMDISKS; i++)
-               register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
+               register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        /* We ought to separate initrd operations here */
index 2d1c1f6d20c6ed7f6b49572e4a35265240e35faf..a62b985aedf0c527ce0d887973ff7e7a82779353 100644 (file)
@@ -217,6 +217,8 @@ static unsigned short command_reg;
 static unsigned short read_status_reg;
 static unsigned short data_reg;
 
+static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
+
 static int initialized;                        /* Has the drive been initialized? */
 static int sony_disc_changed = 1;      /* Has the disk been changed
                                           since the last check? */
@@ -815,123 +817,124 @@ do_cdu535_request(request_queue_t * q)
                        end_request(0);
                        continue;
                }
-               switch (CURRENT->cmd) {
-               case READ:
-                       /*
-                        * If the block address is invalid or the request goes beyond the end of
-                        * the media, return an error.
-                        */
-
-                       if (sony_toc->lead_out_start_lba <= (block / 4)) {
-                               end_request(0);
-                               return;
-                       }
-                       if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
-                               end_request(0);
-                               return;
-                       }
-                       while (0 < nsect) {
+               if(CURRENT->flags & REQ_CMD) {
+                       switch (rq_data_dir(CURRENT)) {
+                       case READ:
                                /*
-                                * If the requested sector is not currently in the read-ahead buffer,
-                                * it must be read in.
+                                * If the block address is invalid or the request goes beyond the end of
+                                * the media, return an error.
                                 */
-                               if ((block < sony_first_block) || (sony_last_block < block)) {
-                                       sony_first_block = (block / 4) * 4;
-                                       log_to_msf(block / 4, params);
-
-                                       /*
-                                        * If the full read-ahead would go beyond the end of the media, trim
-                                        * it back to read just till the end of the media.
-                                        */
-                                       if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
-                                               sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
-                                               read_size = sony_toc->lead_out_start_lba - (block / 4);
-                                       } else {
-                                               sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
-                                               read_size = sony_buffer_sectors;
-                                       }
-                                       size_to_buf(read_size, &params[3]);
-
+                               
+                               if (sony_toc->lead_out_start_lba <= (block / 4)) {
+                                       end_request(0);
+                                       return;
+                               }
+                               if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
+                                       end_request(0);
+                                       return;
+                               }
+                               while (0 < nsect) {
                                        /*
-                                        * Read the data.  If the drive was not spinning,
-                                        * spin it up and try some more.
+                                        * If the requested sector is not currently in the read-ahead buffer,
+                                        * it must be read in.
                                         */
-                                       for (spin_up_retry=0 ;; ++spin_up_retry) {
-                                               /* This loop has been modified to support the Sony
-                                                * CDU-510/515 series, thanks to Claudio Porfiri 
-                                                * <C.Porfiri@nisms.tei.ericsson.se>.
-                                                */
+                                       if ((block < sony_first_block) || (sony_last_block < block)) {
+                                               sony_first_block = (block / 4) * 4;
+                                               log_to_msf(block / 4, params);
+                                               
                                                /*
-                                                * This part is to deal with very slow hardware.  We
-                                                * try at most MAX_SPINUP_RETRY times to read the same
-                                                * block.  A check for seek_and_read_N_blocks' result is
-                                                * performed; if the result is wrong, the CDROM's engine
-                                                * is restarted and the operation is tried again.
+                                                * If the full read-ahead would go beyond the end of the media, trim
+                                                * it back to read just till the end of the media.
                                                 */
+                                               if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
+                                                       sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
+                                                       read_size = sony_toc->lead_out_start_lba - (block / 4);
+                                               } else {
+                                                       sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
+                                                       read_size = sony_buffer_sectors;
+                                               }
+                                               size_to_buf(read_size, &params[3]);
+                                               
                                                /*
-                                                * 1995-06-01: The system got problems when downloading
-                                                * from Slackware CDROM, the problem seems to be:
-                                                * seek_and_read_N_blocks returns BAD_STATUS and we
-                                                * should wait for a while before retrying, so a new
-                                                * part was added to discriminate the return value from
-                                                * seek_and_read_N_blocks for the various cases.
+                                                * Read the data.  If the drive was not spinning,
+                                                * spin it up and try some more.
                                                 */
-                                               int readStatus = seek_and_read_N_blocks(params, read_size,
-                                                                       status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
-                                               if (0 <= readStatus)    /* Good data; common case, placed first */
-                                                       break;
-                                               if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
-                                                       /* give up */
-                                                       if (readStatus == NO_ROOM)
-                                                               printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
-                                                       else
-                                                               printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
-                                                                               status[0]);
-                                                       sony_first_block = -1;
-                                                       sony_last_block = -1;
-                                                       end_request(0);
-                                                       return;
-                                               }
-                                               if (readStatus == BAD_STATUS) {
-                                                       /* Sleep for a while, then retry */
-                                                       current->state = TASK_INTERRUPTIBLE;
-                                                       schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
-                                               }
+                                               for (spin_up_retry=0 ;; ++spin_up_retry) {
+                                                       /* This loop has been modified to support the Sony
+                                                        * CDU-510/515 series, thanks to Claudio Porfiri 
+                                                        * <C.Porfiri@nisms.tei.ericsson.se>.
+                                                        */
+                                                       /*
+                                                        * This part is to deal with very slow hardware.  We
+                                                        * try at most MAX_SPINUP_RETRY times to read the same
+                                                        * block.  A check for seek_and_read_N_blocks' result is
+                                                        * performed; if the result is wrong, the CDROM's engine
+                                                        * is restarted and the operation is tried again.
+                                                        */
+                                                       /*
+                                                        * 1995-06-01: The system got problems when downloading
+                                                        * from Slackware CDROM, the problem seems to be:
+                                                        * seek_and_read_N_blocks returns BAD_STATUS and we
+                                                        * should wait for a while before retrying, so a new
+                                                        * part was added to discriminate the return value from
+                                                        * seek_and_read_N_blocks for the various cases.
+                                                        */
+                                                       int readStatus = seek_and_read_N_blocks(params, read_size,
+                                                                                               status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
+                                                       if (0 <= readStatus)    /* Good data; common case, placed first */
+                                                               break;
+                                                       if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
+                                                               /* give up */
+                                                               if (readStatus == NO_ROOM)
+                                                                       printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
+                                                               else
+                                                                       printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
+                                                                              status[0]);
+                                                               sony_first_block = -1;
+                                                               sony_last_block = -1;
+                                                               end_request(0);
+                                                               return;
+                                                       }
+                                                       if (readStatus == BAD_STATUS) {
+                                                               /* Sleep for a while, then retry */
+                                                               current->state = TASK_INTERRUPTIBLE;
+                                                               schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
+                                                       }
 #if DEBUG > 0
-                                               printk(CDU535_MESSAGE_NAME
-                                                       " debug: calling spin up when reading data!\n");
+                                                       printk(CDU535_MESSAGE_NAME
+                                                              " debug: calling spin up when reading data!\n");
 #endif
-                                               cmd[0] = SONY535_SPIN_UP;
-                                               do_sony_cmd(cmd, 1, status, NULL, 0, 0);
+                                                       cmd[0] = SONY535_SPIN_UP;
+                                                       do_sony_cmd(cmd, 1, status, NULL, 0, 0);
+                                               }
                                        }
+                                       /*
+                                        * The data is in memory now, copy it to the buffer and advance to the
+                                        * next block to read.
+                                        */
+                                       copyoff = block - sony_first_block;
+                                       memcpy(CURRENT->buffer,
+                                              sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
+                                       
+                                       block += 1;
+                                       nsect -= 1;
+                                       CURRENT->buffer += 512;
                                }
-                               /*
-                                * The data is in memory now, copy it to the buffer and advance to the
-                                * next block to read.
-                                */
-                               copyoff = block - sony_first_block;
-                               memcpy(CURRENT->buffer,
-                                          sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
 
-                               block += 1;
-                               nsect -= 1;
-                               CURRENT->buffer += 512;
+                               end_request(1);
+                               break;
+                               
+                       case WRITE:
+                               end_request(0);
+                               break;
+                               
+                       default:
+                               panic("Unknown SONY CD cmd");
                        }
-
-                       end_request(1);
-                       break;
-
-               case WRITE:
-                       end_request(0);
-                       break;
-
-               default:
-                       panic("Unknown SONY CD cmd");
                }
        }
 }
 
-
 /*
  * Read the table of contents from the drive and set sony_toc_read if
  * successful.
@@ -1593,7 +1596,7 @@ sony535_init(void)
                                                        MAJOR_NR, CDU535_MESSAGE_NAME);
                                        return -EIO;
                                }
-                               blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+                               blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, &sonycd535_lock);
                                blksize_size[MAJOR_NR] = &sonycd535_block_size;
                                read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read-ahead */
 
index 0712b3322574a7d18e650ef29531f549331676f2..df2938ade0da1cb2d537578e95209a810baec938 100644 (file)
@@ -117,7 +117,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 static int acq_open(struct inode *inode, struct file *file)
 {
-       switch(MINOR(inode->i_rdev))
+       switch(minor(inode->i_rdev))
        {
                case WATCHDOG_MINOR:
                        spin_lock(&acq_lock);
@@ -141,7 +141,7 @@ static int acq_open(struct inode *inode, struct file *file)
 
 static int acq_close(struct inode *inode, struct file *file)
 {
-       if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
        {
                spin_lock(&acq_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT       
index dfb2663ecf18cb321ae510836d058642f1adec07..b40df81ce0bad98468779107c0b7446c04f84528 100644 (file)
@@ -128,7 +128,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 static int
 advwdt_open(struct inode *inode, struct file *file)
 {
-       switch (MINOR(inode->i_rdev)) {
+       switch (minor(inode->i_rdev)) {
                case WATCHDOG_MINOR:
                        spin_lock(&advwdt_lock);
                        if (advwdt_is_open) {
@@ -151,7 +151,7 @@ advwdt_open(struct inode *inode, struct file *file)
 static int
 advwdt_close(struct inode *inode, struct file *file)
 {
-       if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
                spin_lock(&advwdt_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT       
                inb_p(WDT_STOP);
index 95a66df49796bc67f4cdb523447f6820a1c5ea39..c5ec68e38015f9878a84ef994b67fec364d870c3 100644 (file)
@@ -51,7 +51,7 @@ struct busmouse_data {
 
 #define NR_MICE                        15
 #define FIRST_MOUSE            0
-#define DEV_TO_MOUSE(dev)      MINOR_TO_MOUSE(MINOR(dev))
+#define DEV_TO_MOUSE(dev)      MINOR_TO_MOUSE(minor(dev))
 #define MINOR_TO_MOUSE(minor)  ((minor) - FIRST_MOUSE)
 
 /*
index 3774c85aad531beb5d560ab5ff5474698044b7a2..2907315b6155cacae8955231236e31ccbf4d5492 100644 (file)
@@ -280,7 +280,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
  
 static int eurwdt_open(struct inode *inode, struct file *file)
 {
-   switch (MINOR(inode->i_rdev)) {
+   switch (minor(inode->i_rdev)) {
       case WATCHDOG_MINOR:
          spin_lock(&eurwdt_lock);
          if (eurwdt_is_open) {
@@ -322,7 +322,7 @@ static int eurwdt_open(struct inode *inode, struct file *file)
  
 static int eurwdt_release(struct inode *inode, struct file *file)
 {
-   if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+   if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
       eurwdt_disable_timer();
 #endif
index 51d8fdeb5730a3887fbe2975d646a134b5d87c05..91fb96ca5eb87275a69a9c8cffdad13457057a25 100644 (file)
@@ -155,7 +155,7 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 static int
 ibwdt_open(struct inode *inode, struct file *file)
 {
-       switch (MINOR(inode->i_rdev)) {
+       switch (minor(inode->i_rdev)) {
                case WATCHDOG_MINOR:
                        spin_lock(&ibwdt_lock);
                        if (ibwdt_is_open) {
@@ -179,7 +179,7 @@ static int
 ibwdt_close(struct inode *inode, struct file *file)
 {
        lock_kernel();
-       if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
                spin_lock(&ibwdt_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
                outb_p(WD_TIMO, WDT_STOP);
index 51e67edf1534add310837fd7f5c13fbecaef3b24..efe94e6793d761cd6a922cb97938b9a763505c16 100644 (file)
@@ -149,9 +149,9 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
        char name[32];
 
 #ifdef CONFIG_DEVFS_FS
-       sprintf(name, tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
+       sprintf(name, tty->driver.name, minor(tty->device) - tty->driver.minor_start);
 #else
-       sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
+       sprintf(name, "%s%d", tty->driver.name, minor(tty->device) - tty->driver.minor_start);
 #endif
 
        serio_register_port(&serport->serio);
index e4c0130c7c545d5cb4fdff5954926fcac8ffffb7..85273bc31907ae31ea276feef047055ea7d564fb 100644 (file)
@@ -294,7 +294,7 @@ static int lp_wait_ready(int minor)
 static ssize_t lp_write(struct file * file, const char * buf,
                        size_t count, loff_t *ppos)
 {
-       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
        struct parport *port = lp_table[minor].dev->port;
        char *kbuf = lp_table[minor].lp_buffer;
        ssize_t retv = 0;
@@ -403,7 +403,7 @@ static ssize_t lp_write(struct file * file, const char * buf,
 static ssize_t lp_read(struct file * file, char * buf,
                       size_t count, loff_t *ppos)
 {
-       unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
+       unsigned int minor=minor(file->f_dentry->d_inode->i_rdev);
        struct parport *port = lp_table[minor].dev->port;
        ssize_t retval = 0;
        char *kbuf = lp_table[minor].lp_buffer;
@@ -430,7 +430,7 @@ static ssize_t lp_read(struct file * file, char * buf,
 
 static int lp_open(struct inode * inode, struct file * file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
 
        if (minor >= LP_NO)
                return -ENXIO;
@@ -488,7 +488,7 @@ static int lp_open(struct inode * inode, struct file * file)
 
 static int lp_release(struct inode * inode, struct file * file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
 
        lp_claim_parport_or_block (&lp_table[minor]);
        parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
@@ -503,7 +503,7 @@ static int lp_release(struct inode * inode, struct file * file)
 static int lp_ioctl(struct inode *inode, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        int status;
        int retval = 0;
 
index 75a3b7470c04358f77962963b9504162844c6bf5..8765b677a6dc879d1cc30f17502ef6df373b2424 100644 (file)
@@ -378,7 +378,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 static int zf_open(struct inode *inode, struct file *file)
 {
-       switch(MINOR(inode->i_rdev)){
+       switch(minor(inode->i_rdev)){
                case WATCHDOG_MINOR:
                        spin_lock(&zf_lock);
                        if(zf_is_open){
@@ -403,7 +403,7 @@ static int zf_open(struct inode *inode, struct file *file)
 
 static int zf_close(struct inode *inode, struct file *file)
 {
-       if(MINOR(inode->i_rdev) == WATCHDOG_MINOR){
+       if(minor(inode->i_rdev) == WATCHDOG_MINOR){
 
                if(zf_expect_close){
                        zf_timer_off();
index c85da8a9477cc78783bf2f75fd9d6efc35600c84..a0d4bdc29fa96b08a24031e97d468ffd162d4a40 100644 (file)
@@ -400,7 +400,7 @@ static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
 
 static int pcwd_open(struct inode *ino, struct file *filep)
 {
-        switch (MINOR(ino->i_rdev))
+        switch (minor(ino->i_rdev))
         {
                 case WATCHDOG_MINOR:
                     if ( !atomic_dec_and_test(&open_allowed) )
@@ -433,7 +433,7 @@ static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
        /*  Can't seek (pread) on this device  */
        if (ppos != &file->f_pos)
                return -ESPIPE;
-       switch(MINOR(file->f_dentry->d_inode->i_rdev)) 
+       switch(minor(file->f_dentry->d_inode->i_rdev)) 
        {
                case TEMP_MINOR:
                        /*
@@ -453,7 +453,7 @@ static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
 
 static int pcwd_close(struct inode *ino, struct file *filep)
 {
-       if (MINOR(ino->i_rdev)==WATCHDOG_MINOR)
+       if (minor(ino->i_rdev)==WATCHDOG_MINOR)
        {
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
                /*  Disable the board  */
index 2a2dea8fa9a548dc26c0daef0d961d7659c3d59e..6e976f28c271ae3d1307ceb5f8f18cfa745210ec 100644 (file)
@@ -103,7 +103,7 @@ static inline void pp_enable_irq (struct pp_struct *pp)
 static ssize_t pp_read (struct file * file, char * buf, size_t count,
                        loff_t * ppos)
 {
-       unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev);
+       unsigned int minor = minor (file->f_dentry->d_inode->i_rdev);
        struct pp_struct *pp = file->private_data;
        char * kbuffer;
        ssize_t bytes_read = 0;
@@ -183,7 +183,7 @@ static ssize_t pp_read (struct file * file, char * buf, size_t count,
 static ssize_t pp_write (struct file * file, const char * buf, size_t count,
                         loff_t * ppos)
 {
-       unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev);
+       unsigned int minor = minor (file->f_dentry->d_inode->i_rdev);
        struct pp_struct *pp = file->private_data;
        char * kbuffer;
        ssize_t bytes_written = 0;
@@ -315,7 +315,7 @@ static enum ieee1284_phase init_phase (int mode)
 static int pp_ioctl(struct inode *inode, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct pp_struct *pp = file->private_data;
        struct parport * port;
 
@@ -613,7 +613,7 @@ static int pp_ioctl(struct inode *inode, struct file *file,
 
 static int pp_open (struct inode * inode, struct file * file)
 {
-       unsigned int minor = MINOR (inode->i_rdev);
+       unsigned int minor = minor (inode->i_rdev);
        struct pp_struct *pp;
 
        if (minor >= PARPORT_MAX)
@@ -642,7 +642,7 @@ static int pp_open (struct inode * inode, struct file * file)
 
 static int pp_release (struct inode * inode, struct file * file)
 {
-       unsigned int minor = MINOR (inode->i_rdev);
+       unsigned int minor = minor (inode->i_rdev);
        struct pp_struct *pp = file->private_data;
        int compat_negot;
 
index 5ba8a313a744eee8b13a96a6de8501d2e4a5352e..9c28836d874b1b09365d5b95b5c0f5d7f16c3b6d 100644 (file)
@@ -105,7 +105,7 @@ static struct sysrq_key_op sysrq_reboot_op = {
 /* Guesses if the device is a local hard drive */
 static int is_local_disk(kdev_t dev) {
        unsigned int major;
-       major = MAJOR(dev);
+       major = major(dev);
 
        switch (major) {
        case IDE0_MAJOR:
@@ -206,7 +206,7 @@ void do_emergency_sync(void) {
        for (sb = sb_entry(super_blocks.next);
             sb != sb_entry(&super_blocks); 
             sb = sb_entry(sb->s_list.next))
-               if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev))
+               if (!is_local_disk(sb->s_dev) && major(sb->s_dev))
                        go_sync(sb, remount_flag);
 
        unlock_kernel();
index 78a2a16a3c446daaab20f873a1861c7d9012cd55..cea100d98184be5c072b2297b7391490fd8fd3a3 100644 (file)
@@ -2006,15 +2006,11 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned
        int idx = minor - driver->minor_start;
        char buf[32];
 
-       switch (device) {
-               case TTY_DEV:
-               case PTMX_DEV:
+       if (IS_TTY_DEV(device) || IS_PTMX_DEV(device)) 
+               mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+       else {
+               if (driver->major == PTY_MASTER_MAJOR)
                        mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-                       break;
-               default:
-                       if (driver->major == PTY_MASTER_MAJOR)
-                               mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-                       break;
        }
        if ( (minor <  driver->minor_start) || 
             (minor >= driver->minor_start + driver->num) ) {
index fbf26d0a691b5249e1de8cc40e812a6afef9ac52..f98face6a689eddb0c83697ef98b867b10ba0dd7 100644 (file)
@@ -265,7 +265,7 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
        if (ptr != &file->f_pos)
                return -ESPIPE;
 
-       switch(MINOR(file->f_dentry->d_inode->i_rdev))
+       switch(minor(file->f_dentry->d_inode->i_rdev))
        {
                case TEMP_MINOR:
                        c*=11;
@@ -334,7 +334,7 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
  
 static int wdt_open(struct inode *inode, struct file *file)
 {
-       switch(MINOR(inode->i_rdev))
+       switch(minor(inode->i_rdev))
        {
                case WATCHDOG_MINOR:
                        if(test_and_set_bit(0, &wdt_is_open))
@@ -373,7 +373,7 @@ static int wdt_open(struct inode *inode, struct file *file)
  
 static int wdt_release(struct inode *inode, struct file *file)
 {
-       if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
        {
 #ifndef CONFIG_WATCHDOG_NOWAYOUT       
                inb_p(WDT_DC);          /* Disable counters */
index 8dac309cff3f9db73546044386822cc8b4474fcd..872a5e453ae4ac819039981e39e2cccc49cba012 100644 (file)
@@ -281,7 +281,7 @@ static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *p
        if (ptr != &file->f_pos)
                return -ESPIPE;
 
-       switch(MINOR(file->f_dentry->d_inode->i_rdev))
+       switch(minor(file->f_dentry->d_inode->i_rdev))
        {
                case TEMP_MINOR:
                        c*=11;
@@ -350,7 +350,7 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
  
 static int wdtpci_open(struct inode *inode, struct file *file)
 {
-       switch(MINOR(inode->i_rdev))
+       switch(minor(inode->i_rdev))
        {
                case WATCHDOG_MINOR:
                        if( test_and_set_bit(0,&wdt_is_open) ) 
@@ -410,7 +410,7 @@ static int wdtpci_open(struct inode *inode, struct file *file)
  
 static int wdtpci_release(struct inode *inode, struct file *file)
 {
-       if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
        {
 #ifndef CONFIG_WATCHDOG_NOWAYOUT       
                inb_p(WDT_DC);          /* Disable counters */
index 6d3ab38256aaa7b2634aa9a58716ba73cd069890..3b001b5db0e2530250f4c4bad35951592a6692f0 100644 (file)
@@ -382,7 +382,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
 
 int i2cdev_open (struct inode *inode, struct file *file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct i2c_client *client;
 
        if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
@@ -415,7 +415,7 @@ int i2cdev_open (struct inode *inode, struct file *file)
 
 static int i2cdev_release (struct inode *inode, struct file *file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        kfree(file->private_data);
        file->private_data=NULL;
 #ifdef DEBUG
index 9206953f24fa7d4f6b9cbe35847cce73c626034c..000fe8a453ee0a09f8bc6eede945d24d1ba6101c 100644 (file)
@@ -30,7 +30,7 @@
  * Version 1.11                Highmem I/O support, Jens Axboe <axboe@suse.de>
  */
 
-#define IDEDISK_VERSION        "1.10"
+#define IDEDISK_VERSION        "1.11"
 
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
 
@@ -70,7 +70,7 @@ static void idedisk_bswap_data (void *buffer, int wcount)
        }
 }
 
-static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
        ide_input_data(drive, buffer, wcount);
        if (drive->bswap)
index ba03af19c61b75bbeccf6f6beccad8904337ff31..abdfccd98520a1bf878d2f14f81a4fbf7418da3b 100644 (file)
@@ -595,17 +595,18 @@ static void ide_init_queue(ide_drive_t *drive)
 {
        request_queue_t *q = &drive->queue;
        int max_sectors;
+#ifdef CONFIG_BLK_DEV_PDC4030
+       int is_pdc4030_chipset = (HWIF(drive)->chipset == ide_pdc4030);
+#else
+       const int is_pdc4030_chipset = 0;
+#endif
 
        q->queuedata = HWGROUP(drive);
        blk_init_queue(q, do_ide_request, &ide_lock);
        blk_queue_segment_boundary(q, 0xffff);
 
        /* IDE can do up to 128K per request, pdc4030 needs smaller limit */
-#ifdef CONFIG_BLK_DEV_PDC4030
-       max_sectors = 127;
-#else
-       max_sectors = 255;
-#endif
+       max_sectors = (is_pdc4030_chipset ? 127 : 255);
        blk_queue_max_sectors(q, max_sectors);
 
        /* IDE DMA can do PRD_ENTRIES number of segments. */
index f34006891592e0ee3762a6f1eae8230188ad3387..344dddac29f5bfdec0533af1e397c6b1d794c2ec 100644 (file)
@@ -1241,12 +1241,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
                printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
                goto kill_rq;
        }
-#ifdef DEBUG
-       if (rq->bh && !buffer_locked(rq->bh)) {
-               printk("%s: block not locked\n", drive->name);
-               goto kill_rq;
-       }
-#endif
        block    = rq->sector;
 
        /* Strange disk manager remap */
index d4beef75ae4e516bcf44c64db7df5b2cd05751ce..abafb7afae2ca23e49dcf57f10e29afbe9b8844a 100644 (file)
  * some technical information which has shed a glimmer of light on some of the
  * problems I was having, especially with writes. 
  *
- * There are still problems with the robustness and efficiency of this driver
- * because I still don't understand what the card is doing with interrupts.
+ * There are still potential problems with the robustness and efficiency of
+ * this driver because I still don't understand what the card is doing with
+ * interrupts, however, it has been stable for a while with no reports of ill
+ * effects.
  */
 
 #define DEBUG_READ
@@ -308,7 +310,9 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
        byte stat;
        int total_remaining;
        unsigned int sectors_left, sectors_avail, nsect;
+       unsigned long flags;
        struct request *rq;
+       char *to;
 
        if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
                return ide_error(drive, "promise_read_intr", stat);
@@ -330,15 +334,15 @@ read_next:
        if (nsect > sectors_avail)
                nsect = sectors_avail;
        sectors_avail -= nsect;
-       ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
+       to = ide_map_buffer(rq, &flags);
+       idedisk_input_data(drive, to, nsect * SECTOR_WORDS);
 #ifdef DEBUG_READ
        printk(KERN_DEBUG "%s:  promise_read: sectors(%ld-%ld), "
               "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector,
-              rq->sector+nsect-1, (unsigned long) rq->buffer,
-              rq->nr_sectors-nsect);
+              rq->sector+nsect-1, (unsigned long) to, rq->nr_sectors-nsect);
 #endif
+       ide_unmap_buffer(to, &flags);
        rq->sector += nsect;
-       rq->buffer += nsect<<9;
        rq->errors = 0;
        rq->nr_sectors -= nsect;
        total_remaining = rq->nr_sectors;
@@ -406,10 +410,7 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
 #ifdef DEBUG_WRITE
        printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
 #endif
-       for (i = rq->nr_sectors; i > 0; ) {
-               i -= rq->current_nr_sectors;
-               ide_end_request(1, hwgroup);
-       }
+       __ide_end_request(hwgroup, 1, rq->nr_sectors);
        return ide_stopped;
 }
 
@@ -498,7 +499,15 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
        unsigned long timeout;
        byte stat;
 
-       if (rq->cmd == READ) {
+/* Check that it's a regular command. If not, bomb out early. */
+       if (!(rq->flags & REQ_CMD)) {
+               blk_dump_rq_flags(rq, "pdc4030 bad flags");
+               ide_end_request(0, HWGROUP(drive));
+               return ide_stopped;
+       }
+
+       switch (rq_data_dir(rq)) {
+       case READ:
                OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
 /*
  * The card's behaviour is odd at this point. If the data is
@@ -531,9 +540,18 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
                printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n",
                        drive->name);
                return ide_stopped;
-       } else if (rq->cmd == WRITE) {
+               break;
+
+       case WRITE:
                ide_startstop_t startstop;
                OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
+/*
+ * Strategy on write is:
+ *     look for the DRQ that should have been immediately asserted
+ *     copy the request into the hwgroup's scratchpad
+ *     call the promise_write function to deal with writing the data out
+ * NOTE: No interrupts are generated on writes. Write completion must be polled
+ */
                if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
                        printk(KERN_ERR "%s: no DRQ after issuing "
                               "PROMISE_WRITE\n", drive->name);
@@ -543,11 +561,11 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
                        __cli();        /* local CPU only */
                HWGROUP(drive)->wrq = *rq; /* scratchpad */
                return promise_write(drive);
+               break;
 
-       } else {
-               printk("KERN_WARNING %s: bad command: %d\n",
-                      drive->name, rq->cmd);
+       default:
+               printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
                ide_end_request(0, HWGROUP(drive));
-               return ide_stopped;
+               break;
        }
 }
index 531b07eddac888640cbad7f6171cfad1892179b3..62f5adcdde4d7d45cbe87aa00262850d3d54d9c7 100644 (file)
@@ -119,7 +119,7 @@ static int evdev_release(struct inode * inode, struct file * file)
 static int evdev_open(struct inode * inode, struct file * file)
 {
        struct evdev_list *list;
-       int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE;
+       int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
 
        if (i >= EVDEV_MINORS || !evdev_table[i])
                return -ENODEV;
index 8c1775d606737e433ab0587600a47e3d4e2280ad..eb7fe0f1729c102afb304ae64c8eff51e6e83297 100644 (file)
@@ -368,7 +368,7 @@ void input_unregister_handler(struct input_handler *handler)
 
 static int input_open_file(struct inode *inode, struct file *file)
 {
-       struct input_handler *handler = input_table[MINOR(inode->i_rdev) >> 5];
+       struct input_handler *handler = input_table[minor(inode->i_rdev) >> 5];
        struct file_operations *old_fops, *new_fops = NULL;
        int err;
 
index be18380e8cf7c3242b145935ab62644019739624..f17165bddc0ab831a19a7d1e17b083ec4d6b9d8d 100644 (file)
@@ -189,7 +189,7 @@ static int joydev_release(struct inode * inode, struct file * file)
 static int joydev_open(struct inode *inode, struct file *file)
 {
        struct joydev_list *list;
-       int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE;
+       int i = minor(inode->i_rdev) - JOYDEV_MINOR_BASE;
 
        if (i >= JOYDEV_MINORS || !joydev_table[i])
                return -ENODEV;
index f9993eded5438bd695076abff40a35af9b22e018..c37b6a0ddd7657aced5efa5a9f2cffaf56e36acc 100644 (file)
@@ -214,7 +214,7 @@ static int mousedev_release(struct inode * inode, struct file * file)
 static int mousedev_open(struct inode * inode, struct file * file)
 {
        struct mousedev_list *list;
-       int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
+       int i = minor(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
 
        if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
                return -ENODEV;
index 707940b33a165d596cd8db89f9f8e7b9da4c28c6..77e8488ce86e251d6aa050ecd2958876c0a15677 100644 (file)
@@ -42,6 +42,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
    fi
    bool '  HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
    bool '  HiSax Support for US NI1' CONFIG_HISAX_NI1
+   int  '  Maximum number of cards supported by HiSax' CONFIG_HISAX_MAX_CARDS 8
    comment '  HiSax supported cards'
    bool '  Teles 16.0/8.0' CONFIG_HISAX_16_0
    bool '  Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
@@ -81,7 +82,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
    dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
    dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
    dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
-   dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
+   dep_tristate 'AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
 fi
 endmenu
 
index e33fb0d8dd41efea897e3a650a4420a44bdb4ded..15e4a2b9b2c7089485af5e5ebb47bf701ab8d17b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: avmcard.h,v 1.8.6.4 2001/09/23 22:24:33 kai Exp $
+/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  *
  * Copyright 1999 by Carsten Paeth <calle@calle.de>
  *
@@ -39,13 +39,21 @@ enum avmcardtype {
        avm_c2
 };
 
+typedef struct avmcard_dmabuf {
+    long        size;
+    __u8       *dmabuf;
+    dma_addr_t  dmaaddr;
+} avmcard_dmabuf;
+
 typedef struct avmcard_dmainfo {
-       __u32 recvlen;   
-       __u8  recvbuf[128+2048];
-       struct sk_buff_head send_queue;
-       __u8  sendbuf[128+2048];
-} avmcard_dmainfo;
+       __u32                recvlen;
+        avmcard_dmabuf       recvbuf;
+
+        avmcard_dmabuf       sendbuf;
+       struct sk_buff_head  send_queue;
 
+       struct pci_dev      *pcidev;
+} avmcard_dmainfo;
 
 typedef struct avmcard {
        char name[32];
@@ -544,6 +552,11 @@ void b1_handle_interrupt(avmcard * card);
 int b1ctl_read_proc(char *page, char **start, off_t off,
                        int count, int *eof, struct capi_ctr *ctrl);
 
+avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
+                                  long rsize, long ssize);
+void avmcard_dma_free(avmcard_dmainfo *);
+
+
 /* b1dma.c */
 int b1pciv4_detect(avmcard *card);
 int t1pci_detect(avmcard *card);
index bf8a49bcef056fc3e62eb3e6ebf7da259bb1a462..38430213fccc83d0559b52d03589924e3eac229f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: b1.c,v 1.20.6.7 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Common module for AVM B1 cards.
  * 
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/pci.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
@@ -27,7 +28,7 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.20.6.7 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 /* ------------------------------------------------------------- */
 
@@ -639,6 +640,65 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
 
 /* ------------------------------------------------------------- */
 
+#ifdef CONFIG_PCI
+
+avmcard_dmainfo *
+avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
+{
+       avmcard_dmainfo *p;
+       void *buf;
+
+       p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
+       if (!p) {
+               printk(KERN_WARNING "%s: no memory.\n", name);
+               goto err;
+       }
+       memset(p, 0, sizeof(avmcard_dmainfo));
+
+       p->recvbuf.size = rsize;
+       buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
+       if (!buf) {
+               printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name);
+               goto err_kfree;
+       }
+       p->recvbuf.dmabuf = buf;
+
+       p->sendbuf.size = ssize;
+       buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr);
+       if (!buf) {
+               printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name);
+               goto err_free_consistent;
+       }
+
+       p->sendbuf.dmabuf = buf;
+       skb_queue_head_init(&p->send_queue);
+
+       return p;
+
+ err_free_consistent:
+       pci_free_consistent(p->pcidev, p->recvbuf.size,
+                           p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
+ err_kfree:
+       kfree(p);
+ err:
+       return 0;
+}
+
+void avmcard_dma_free(avmcard_dmainfo *p)
+{
+       pci_free_consistent(p->pcidev, p->recvbuf.size,
+                           p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
+       pci_free_consistent(p->pcidev, p->sendbuf.size,
+                           p->sendbuf.dmabuf, p->sendbuf.dmaaddr);
+       skb_queue_purge(&p->send_queue);
+       kfree(p);
+}
+
+EXPORT_SYMBOL(avmcard_dma_alloc);
+EXPORT_SYMBOL(avmcard_dma_free);
+
+#endif
+
 EXPORT_SYMBOL(b1_irq_table);
 
 EXPORT_SYMBOL(b1_detect);
index c948463f6d1560a9dd8dce0fe9636f5964be9323..f8b0320b31cc6194dd8532d618bb1832fa39c2b0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: b1dma.c,v 1.11.6.8 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Common module for AVM B1 cards that support dma with AMCC
  * 
@@ -32,7 +32,7 @@
 #error FIXME: driver requires 32-bit platform
 #endif
 
-static char *revision = "$Revision: 1.11.6.8 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 /* ------------------------------------------------------------- */
 
@@ -388,7 +388,7 @@ static void b1dma_dispatch_tx(avmcard *card)
                cmd = CAPIMSG_COMMAND(skb->data);
                subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 
-               p = dma->sendbuf;
+               p = dma->sendbuf.dmabuf;
 
                if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
                        __u16 dlen = CAPIMSG_DATALEN(skb->data);
@@ -399,7 +399,7 @@ static void b1dma_dispatch_tx(avmcard *card)
                        _put_byte(&p, SEND_MESSAGE);
                        _put_slice(&p, skb->data, len);
                }
-               txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+               txlen = (__u8 *)p - (__u8 *)dma->sendbuf.dmabuf;
 #ifdef CONFIG_B1DMA_DEBUG
                printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
                                inint, txlen);
@@ -414,11 +414,11 @@ static void b1dma_dispatch_tx(avmcard *card)
                printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
                                inint, skb->data[2], txlen);
 #endif
-               memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+               memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
        }
        txlen = (txlen + 3) & ~3;
 
-       b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
+       b1dmaoutmeml(card->mbase+AMCC_TXPTR, dma->sendbuf.dmaaddr);
        b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen);
 
        card->csr |= EN_TX_TC_INT;
@@ -461,7 +461,7 @@ static void b1dma_handle_rx(avmcard *card)
        avmcard_dmainfo *dma = card->dma;
        struct capi_ctr *ctrl = cinfo->capi_ctrl;
        struct sk_buff *skb;
-       void *p = dma->recvbuf+4;
+       void *p = dma->recvbuf.dmabuf+4;
        __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
        __u8 b1cmd =  _get_byte(&p);
 
@@ -597,18 +597,19 @@ static void b1dma_handle_interrupt(avmcard *card)
        b1dmaoutmeml(card->mbase+AMCC_INTCSR, newcsr);
 
        if ((status & RX_TC_INT) != 0) {
-               __u8 *recvbuf = card->dma->recvbuf;
+               struct avmcard_dmainfo *dma = card->dma;
                __u32 rxlen;
                if (card->dma->recvlen == 0) {
-                       card->dma->recvlen = *((__u32 *)recvbuf);
-                       rxlen = (card->dma->recvlen + 3) & ~3;
+                       dma->recvlen = *((__u32 *)dma->recvbuf.dmabuf);
+                       rxlen = (dma->recvlen + 3) & ~3;
                        b1dmaoutmeml(card->mbase+AMCC_RXPTR,
-                                       virt_to_phys(recvbuf+4));
+                                       dma->recvbuf.dmaaddr+4);
                        b1dmaoutmeml(card->mbase+AMCC_RXLEN, rxlen);
                } else {
                        b1dma_handle_rx(card);
-                       card->dma->recvlen = 0;
-                       b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
+                       dma->recvlen = 0;
+                       b1dmaoutmeml(card->mbase+AMCC_RXPTR,
+                                       dma->recvbuf.dmaaddr);
                        b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
                }
        }
@@ -744,7 +745,7 @@ int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
        t1outp(card->port, 0x10, 0xF0);
 
        card->dma->recvlen = 0;
-       b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
+       b1dmaoutmeml(card->mbase+AMCC_RXPTR, card->dma->recvbuf.dmaaddr);
        b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
        card->csr |= EN_RX_TC_INT;
        b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
@@ -855,7 +856,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
        __u8 flag;
        int len = 0;
        char *s;
-       __u32 txaddr, txlen, rxaddr, rxlen, csr;
+       __u32 txoff, txlen, rxoff, rxlen, csr;
 
        len += sprintf(page+len, "%-16s %s\n", "name", card->name);
        len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
@@ -911,13 +912,11 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
        save_flags(flags);
        cli();
 
-       txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
-       txaddr -= (__u32)card->dma->sendbuf;
-       txlen  = b1dmainmeml(card->mbase+0x30);
+       txoff = (dma_addr_t)b1dmainmeml(card->mbase+0x2c)-card->dma->sendbuf.dmaaddr;
+       txlen = b1dmainmeml(card->mbase+0x30);
 
-       rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24));
-       rxaddr -= (__u32)card->dma->recvbuf;
-       rxlen  = b1dmainmeml(card->mbase+0x28);
+       rxoff = (dma_addr_t)b1dmainmeml(card->mbase+0x24)-card->dma->recvbuf.dmaaddr;
+       rxlen = b1dmainmeml(card->mbase+0x28);
 
        csr  = b1dmainmeml(card->mbase+AMCC_INTCSR);
 
@@ -928,11 +927,11 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
         len += sprintf(page+len, "%-16s 0x%lx\n",
                                "csr", (unsigned long)csr);
         len += sprintf(page+len, "%-16s %lu\n",
-                               "txoff", (unsigned long)txaddr);
+                               "txoff", (unsigned long)txoff);
         len += sprintf(page+len, "%-16s %lu\n",
                                "txlen", (unsigned long)txlen);
         len += sprintf(page+len, "%-16s %lu\n",
-                               "rxoff", (unsigned long)rxaddr);
+                               "rxoff", (unsigned long)rxoff);
         len += sprintf(page+len, "%-16s %lu\n",
                                "rxlen", (unsigned long)rxlen);
 
index ef38a321ee8d9fb5602234e67d30450d145dc8fd..7c378f031370f05ac969e627e94c005b661630f5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: b1pci.c,v 1.29.6.5 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Module for AVM B1 PCI-card.
  * 
@@ -26,7 +26,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.29.6.5 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 /* ------------------------------------------------------------- */
 
@@ -108,7 +108,9 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl)
 
 /* ------------------------------------------------------------- */
 
-static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int b1pci_add_card(struct capi_driver *driver,
+                          struct capicardparams *p,
+                         struct pci_dev *dev)
 {
        avmcard *card;
        avmctrl_info *cinfo;
@@ -237,7 +239,7 @@ static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
        release_region(card->port, AVMB1_PORTLEN);
        ctrl->driverdata = 0;
        kfree(card->ctrlinfo);
-       kfree(card->dma);
+        avmcard_dma_free(card->dma);
        kfree(card);
 
        MOD_DEC_USE_COUNT;
@@ -262,7 +264,9 @@ static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
 
 /* ------------------------------------------------------------- */
 
-static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int b1pciv4_add_card(struct capi_driver *driver,
+                            struct capicardparams *p,
+                           struct pci_dev *dev)
 {
        avmcard *card;
        avmctrl_info *cinfo;
@@ -278,18 +282,17 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
                return -ENOMEM;
        }
        memset(card, 0, sizeof(avmcard));
-       card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+        card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
        if (!card->dma) {
-               printk(KERN_WARNING "%s: no memory.\n", driver->name);
+               printk(KERN_WARNING "%s: dma alloc.\n", driver->name);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
        }
-       memset(card->dma, 0, sizeof(avmcard_dmainfo));
         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
        if (!cinfo) {
                printk(KERN_WARNING "%s: no memory.\n", driver->name);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
@@ -308,7 +311,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
                       "%s: ports 0x%03x-0x%03x in use.\n",
                       driver->name, card->port, card->port + AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
@@ -319,7 +322,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
                printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
                                        driver->name, card->membase);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EIO;
@@ -332,7 +335,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
                                        driver->name, card->port, retval);
                 iounmap(card->mbase);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EIO;
@@ -349,7 +352,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
                 iounmap(card->mbase);
                release_region(card->port, AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
@@ -362,15 +365,13 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
                free_irq(card->irq, card);
                release_region(card->port, AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
        }
        card->cardnr = cinfo->capi_ctrl->cnr;
 
-       skb_queue_head_init(&card->dma->send_queue);
-
        printk(KERN_INFO
                "%s: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
                driver->name, card->port, card->irq,
@@ -429,9 +430,9 @@ static int add_card(struct pci_dev *dev)
                "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
                driver->name, param.port, param.irq, param.membase);
 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
-               retval = b1pciv4_add_card(driver, &param);
+               retval = b1pciv4_add_card(driver, &param, dev);
 #else
-               retval = b1pci_add_card(driver, &param);
+               retval = b1pci_add_card(driver, &param, dev);
 #endif
                if (retval != 0) {
                        printk(KERN_ERR
@@ -445,7 +446,7 @@ static int add_card(struct pci_dev *dev)
                printk(KERN_INFO
                "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
                driver->name, param.port, param.irq);
-               retval = b1pci_add_card(driver, &param);
+               retval = b1pci_add_card(driver, &param, dev);
                if (retval != 0) {
                        printk(KERN_ERR
                        "%s: no AVM-B1 at i/o %#x, irq %d detected\n",
index b9d66d69ddf2db91828cadab61e6b6b8a353ef20..6cbe16d1880adc480e26b2af9067d8150e6bc88e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: c4.c,v 1.20.6.11 2001/09/23 22:24:33 kai Exp $
+/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Module for AVM C4 & C2 card.
  * 
@@ -29,7 +29,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.20.6.11 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 #undef CONFIG_C4_DEBUG
 #undef CONFIG_C4_POLLDEBUG
@@ -439,7 +439,7 @@ static void c4_dispatch_tx(avmcard *card)
                cmd = CAPIMSG_COMMAND(skb->data);
                subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 
-               p = dma->sendbuf;
+               p = dma->sendbuf.dmabuf;
 
                if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
                        __u16 dlen = CAPIMSG_DATALEN(skb->data);
@@ -450,7 +450,7 @@ static void c4_dispatch_tx(avmcard *card)
                        _put_byte(&p, SEND_MESSAGE);
                        _put_slice(&p, skb->data, len);
                }
-               txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+               txlen = (__u8 *)p - (__u8 *)dma->sendbuf.dmabuf;
 #ifdef CONFIG_C4_DEBUG
                printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
 #endif
@@ -464,11 +464,11 @@ static void c4_dispatch_tx(avmcard *card)
                printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
                                card->name, skb->data[2], txlen);
 #endif
-               memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+               memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
        }
        txlen = (txlen + 3) & ~3;
 
-       c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf));
+       c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr);
        c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);
 
        card->csr |= DBELL_DOWN_ARM;
@@ -510,7 +510,7 @@ static void c4_handle_rx(avmcard *card)
        struct capi_ctr *ctrl;
        avmctrl_info *cinfo;
        struct sk_buff *skb;
-       void *p = dma->recvbuf;
+       void *p = dma->recvbuf.dmabuf;
        __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
        __u8 b1cmd =  _get_byte(&p);
        __u32 cidx;
@@ -702,7 +702,7 @@ static void c4_handle_interrupt(avmcard *card)
                c4outmeml(card->mbase+MBOX_UP_LEN, 0);
                c4_handle_rx(card);
                card->dma->recvlen = 0;
-               c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+               c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
                c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
        }
 
@@ -885,8 +885,8 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
        c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08);
 
        card->dma->recvlen = 0;
-       c4outmeml(card->mbase+MBOX_UP_ADDR, virt_to_phys(card->dma->recvbuf));
-       c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+       c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr);
+       c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
        c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
        restore_flags(flags);
 
@@ -944,7 +944,7 @@ static void c4_remove_ctr(struct capi_ctr *ctrl)
        release_region(card->port, AVMB1_PORTLEN);
        ctrl->driverdata = 0;
        kfree(card->ctrlinfo);
-       kfree(card->dma);
+        avmcard_dma_free(card->dma);
        kfree(card);
 
        MOD_DEC_USE_COUNT;
@@ -1123,6 +1123,7 @@ static int c4_read_proc(char *page, char **start, off_t off,
 
 static int c4_add_card(struct capi_driver *driver,
                       struct capicardparams *p,
+                       struct pci_dev *dev,
                       int nr)
 {
        avmctrl_info *cinfo;
@@ -1140,18 +1141,17 @@ static int c4_add_card(struct capi_driver *driver,
                return -ENOMEM;
        }
        memset(card, 0, sizeof(avmcard));
-       card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+        card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
        if (!card->dma) {
                printk(KERN_WARNING "%s: no memory.\n", driver->name);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
        }
-       memset(card->dma, 0, sizeof(avmcard_dmainfo));
         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
        if (!cinfo) {
                printk(KERN_WARNING "%s: no memory.\n", driver->name);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
@@ -1173,7 +1173,7 @@ static int c4_add_card(struct capi_driver *driver,
                       "%s: ports 0x%03x-0x%03x in use.\n",
                       driver->name, card->port, card->port + AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
@@ -1184,7 +1184,7 @@ static int c4_add_card(struct capi_driver *driver,
                printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
                                        driver->name, card->membase);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EIO;
@@ -1195,7 +1195,7 @@ static int c4_add_card(struct capi_driver *driver,
                                        driver->name, card->port, retval);
                 iounmap(card->mbase);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EIO;
@@ -1211,7 +1211,7 @@ static int c4_add_card(struct capi_driver *driver,
                 iounmap(card->mbase);
                release_region(card->port, AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+                avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
@@ -1231,7 +1231,7 @@ static int c4_add_card(struct capi_driver *driver,
                        iounmap(card->mbase);
                        free_irq(card->irq, card);
                        release_region(card->port, AVMB1_PORTLEN);
-                       kfree(card->dma);
+                        avmcard_dma_free(card->dma);
                        kfree(card->ctrlinfo);
                        kfree(card);
                        MOD_DEC_USE_COUNT;
@@ -1241,8 +1241,6 @@ static int c4_add_card(struct capi_driver *driver,
                        card->cardnr = cinfo->capi_ctrl->cnr;
        }
 
-       skb_queue_head_init(&card->dma->send_queue);
-
        printk(KERN_INFO
                "%s: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
                driver->name, nr, card->port, card->irq, card->membase);
@@ -1335,7 +1333,7 @@ static int __init search_cards(struct capi_driver * driver,
                printk(KERN_INFO
                        "%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
                        driver->name, nr, param.port, param.irq, param.membase);
-               retval = c4_add_card(driver, &param, nr);
+               retval = c4_add_card(driver, &param, dev, nr);
                if (retval != 0) {
                        printk(KERN_ERR
                        "%s: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
index e8b35afd5ed20d60b08637711e21b29d012840d5..1810f3dc29494e86885828921206a769d1747b00 100644 (file)
@@ -129,11 +129,9 @@ struct capincci {
 };
 
 struct capidev {
-       struct capidev *next;
-       struct file    *file;
+       struct list_head list;
        u16             applid;
        u16             errcode;
-       unsigned int    minor;
        unsigned        userflags;
 
        struct sk_buff_head recvqueue;
@@ -150,17 +148,18 @@ struct capidev {
 
 /* -------- global variables ---------------------------------------- */
 
-static struct capi_interface *capifuncs = 0;
-static struct capidev *capidev_openlist = 0;
+static struct capi_interface *capifuncs;
+static rwlock_t capidev_list_lock;
+static LIST_HEAD(capidev_list);
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-static struct capiminor *minors = 0;
+static struct capiminor *minors;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
-static kmem_cache_t *capidev_cachep = 0;
-static kmem_cache_t *capincci_cachep = 0;
+static kmem_cache_t *capidev_cachep;
+static kmem_cache_t *capincci_cachep;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-static kmem_cache_t *capiminor_cachep = 0;
-static kmem_cache_t *capidh_cachep = 0;
+static kmem_cache_t *capiminor_cachep;
+static kmem_cache_t *capidh_cachep;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -318,9 +317,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
                printk(KERN_DEBUG "set mp->nccip\n");
 #endif
 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
-               kdev = MKDEV(capi_rawmajor, mp->minor);
+               kdev = mk_kdev(capi_rawmajor, mp->minor);
                capifs_new_ncci('r', mp->minor, kdev);
-               kdev = MKDEV(capi_ttymajor, mp->minor);
+               kdev = mk_kdev(capi_ttymajor, mp->minor);
                capifs_new_ncci(0, mp->minor, kdev);
 #endif
        }
@@ -391,48 +390,52 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
 static struct capidev *capidev_alloc(struct file *file)
 {
        struct capidev *cdev;
-       struct capidev **pp;
+       unsigned long flags;
 
        cdev = (struct capidev *)kmem_cache_alloc(capidev_cachep, GFP_KERNEL);
        if (!cdev)
                return 0;
        memset(cdev, 0, sizeof(struct capidev));
-       cdev->file = file;
-       cdev->minor = MINOR(file->f_dentry->d_inode->i_rdev);
 
        skb_queue_head_init(&cdev->recvqueue);
        init_waitqueue_head(&cdev->recvwait);
-       pp=&capidev_openlist;
-       while (*pp) pp = &(*pp)->next;
-       *pp = cdev;
+       write_lock_irqsave(&capidev_list_lock, flags);
+       list_add_tail(&cdev->list, &capidev_list);
+       write_unlock_irqrestore(&capidev_list_lock, flags);
         return cdev;
 }
 
 static void capidev_free(struct capidev *cdev)
 {
-       struct capidev **pp;
+       unsigned long flags;
 
        if (cdev->applid)
                (*capifuncs->capi_release) (cdev->applid);
        cdev->applid = 0;
-
        skb_queue_purge(&cdev->recvqueue);
-       
-       pp=&capidev_openlist;
-       while (*pp && *pp != cdev) pp = &(*pp)->next;
-       if (*pp)
-               *pp = cdev->next;
-
+       write_lock_irqsave(&capidev_list_lock, flags);
+       list_del(&cdev->list);
+       write_unlock_irqrestore(&capidev_list_lock, flags);
        kmem_cache_free(capidev_cachep, cdev);
 }
 
 static struct capidev *capidev_find(u16 applid)
 {
-       struct capidev *p;
-       for (p=capidev_openlist; p; p = p->next) {
+       // FIXME this doesn't guarantee that the device won't go away shortly
+       struct list_head *l;
+       struct capidev *p = NULL;
+
+       read_lock(&capidev_list_lock);
+       list_for_each(l, &capidev_list) {
+               p = list_entry(l, struct capidev, list);
                if (p->applid == applid)
                        break;
        }
+       read_unlock(&capidev_list_lock);
+       
+       if (l == &capidev_list)
+               return NULL;
+       
        return p;
 }
 
@@ -1088,7 +1091,7 @@ capinc_raw_open(struct inode *inode, struct file *file)
 
        if (file->private_data)
                return -EEXIST;
-       if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
+       if ((mp = capiminor_find(minor(file->f_dentry->d_inode->i_rdev))) == 0)
                return -ENXIO;
        if (mp->nccip == 0)
                return -ENXIO;
@@ -1272,7 +1275,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
 {
        struct capiminor *mp;
 
-       if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
+       if ((mp = capiminor_find(minor(file->f_dentry->d_inode->i_rdev))) == 0)
                return -ENXIO;
        if (mp->nccip == 0)
                return -ENXIO;
@@ -1662,11 +1665,13 @@ static int proc_capidev_read_proc(char *page, char **start, off_t off,
                                        int count, int *eof, void *data)
 {
         struct capidev *cdev;
+       struct list_head *l;
        int len = 0;
 
-       for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
-               len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n",
-                       cdev->minor,
+       read_lock(&capidev_list_lock);
+       list_for_each(l, &capidev_list) {
+               cdev = list_entry(l, struct capidev, list);
+               len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n",
                        cdev->applid,
                        cdev->nrecvctlpkt,
                        cdev->nrecvdatapkt,
@@ -1680,11 +1685,13 @@ static int proc_capidev_read_proc(char *page, char **start, off_t off,
                                goto endloop;
                }
        }
+
 endloop:
+       read_unlock(&capidev_list_lock);
        if (len < count)
                *eof = 1;
-       if (len>count) len = count;
-       if (len<0) len = 0;
+       if (len > count) len = count;
+       if (len < 0) len = 0;
        return len;
 }
 
@@ -1697,9 +1704,12 @@ static int proc_capincci_read_proc(char *page, char **start, off_t off,
 {
         struct capidev *cdev;
         struct capincci *np;
+       struct list_head *l;
        int len = 0;
 
-       for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
+       read_lock(&capidev_list_lock);
+       list_for_each(l, &capidev_list) {
+               cdev = list_entry(l, struct capidev, list);
                for (np=cdev->nccis; np; np = np->next) {
                        len += sprintf(page+len, "%d 0x%x%s\n",
                                cdev->applid,
@@ -1719,6 +1729,7 @@ static int proc_capincci_read_proc(char *page, char **start, off_t off,
                }
        }
 endloop:
+       read_unlock(&capidev_list_lock);
        *start = page+off;
        if (len < count)
                *eof = 1;
index 745b6bd112cbbad4d36607790437e91746ee2179..823b3473702ebcc7f085b9585c63437bc0948406 100644 (file)
@@ -430,7 +430,7 @@ void capifs_new_ncci(char type, unsigned int num, kdev_t device)
                        inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
                        inode->i_nlink = 1;
                        inode->i_ino = ino + 2;
-                       init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
+                       init_special_inode(inode, sbi->mode|S_IFCHR, kdev_t_to_nr(np->kdev));
                }
        }
 }
index 79aa41a87f9b78beaaf387e15c6c818734fb56cf..4aa72aa3209b2364b757f8e90ed8ad82e8808d34 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t1pci.c,v 1.13.6.6 2001/09/23 22:24:34 kai Exp $
+/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
  * 
  * Module for AVM T1 PCI-card.
  * 
@@ -26,7 +26,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.13.6.6 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
 
 #undef CONFIG_T1PCI_DEBUG
 #undef CONFIG_T1PCI_POLLDEBUG
@@ -62,7 +62,7 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
        release_region(card->port, AVMB1_PORTLEN);
        ctrl->driverdata = 0;
        kfree(card->ctrlinfo);
-       kfree(card->dma);
+       avmcard_dma_free(card->dma);
        kfree(card);
 
        MOD_DEC_USE_COUNT;
@@ -70,7 +70,9 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
 
 /* ------------------------------------------------------------- */
 
-static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int t1pci_add_card(struct capi_driver *driver,
+                          struct capicardparams *p,
+                         struct pci_dev *dev)
 {
        avmcard *card;
        avmctrl_info *cinfo;
@@ -86,18 +88,17 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
                return -ENOMEM;
        }
        memset(card, 0, sizeof(avmcard));
-       card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+        card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
        if (!card->dma) {
                printk(KERN_WARNING "%s: no memory.\n", driver->name);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
        }
-       memset(card->dma, 0, sizeof(avmcard_dmainfo));
         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
        if (!cinfo) {
                printk(KERN_WARNING "%s: no memory.\n", driver->name);
-               kfree(card->dma);
+               avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
@@ -116,7 +117,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
                       "%s: ports 0x%03x-0x%03x in use.\n",
                       driver->name, card->port, card->port + AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+               avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
@@ -127,7 +128,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
                printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
                                        driver->name, card->membase);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+               avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EIO;
@@ -144,7 +145,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
                                        driver->name, card->port, retval);
                 iounmap(card->mbase);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+               avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EIO;
@@ -160,7 +161,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
                 iounmap(card->mbase);
                release_region(card->port, AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+               avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
@@ -173,15 +174,13 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
                free_irq(card->irq, card);
                release_region(card->port, AVMB1_PORTLEN);
                kfree(card->ctrlinfo);
-               kfree(card->dma);
+               avmcard_dma_free(card->dma);
                kfree(card);
                MOD_DEC_USE_COUNT;
                return -EBUSY;
        }
        card->cardnr = cinfo->capi_ctrl->cnr;
 
-       skb_queue_head_init(&card->dma->send_queue);
-
        printk(KERN_INFO
                "%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
                driver->name, card->port, card->irq, card->membase);
@@ -271,7 +270,7 @@ static int __init t1pci_init(void)
                printk(KERN_INFO
                        "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
                        driver->name, param.port, param.irq, param.membase);
-               retval = t1pci_add_card(driver, &param);
+               retval = t1pci_add_card(driver, &param, dev);
                if (retval != 0) {
                        printk(KERN_ERR
                        "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
index 0b49772e80d89f2b982f86b86fdae35cb7fd3b4f..ef6aaca1a42dbbf0428d9836c6c9cf65a9460180 100644 (file)
@@ -4,6 +4,10 @@
 
 O_TARGET         := vmlinux-obj.o
 
+# Define maximum number of cards
+
+EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+
 # Objects that export symbols.
 
 export-objs      := config.o fsm.o hisax_isac.o
index 583fec93172e785c3d7ab72ef7780fc4ff7ccfaa..56f2e69bee9aa9026b24755f4e4e82f48164c140 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 2.57.6.20 2001/09/23 22:24:47 kai Exp $
+/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $
  *
  * Author       Karsten Keil
  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
@@ -336,27 +336,19 @@ EXPORT_SYMBOL(HiSax_closecard);
        NULL, \
 }
 
-#define EMPTY_CARD     {0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
-
-struct IsdnCard cards[] = {
+struct IsdnCard cards[HISAX_MAX_CARDS] = {
        FIRST_CARD,
-       EMPTY_CARD,
-       EMPTY_CARD,
-       EMPTY_CARD,
-       EMPTY_CARD,
-       EMPTY_CARD,
-       EMPTY_CARD,
-       EMPTY_CARD,
 };
 
-static char HiSaxID[64] __devinitdata = { 0, };
+#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
+static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, };
 
 char *HiSax_id __devinitdata = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
-static int type[8] __devinitdata = { 0, };
-static int protocol[8] __devinitdata = { 0, };
-static int io[8] __devinitdata = { 0, };
+static int type[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int io[HISAX_MAX_CARDS] __devinitdata = { 0, };
 #undef IO0_IO1
 #ifdef CONFIG_HISAX_16_3
 #define IO0_IO1
@@ -366,25 +358,27 @@ static int io[8] __devinitdata = { 0, };
 #define IO0_IO1
 #endif
 #ifdef IO0_IO1
-static int io0[8] __devinitdata = { 0, };
-static int io1[8] __devinitdata = { 0, };
+static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
 #endif
-static int irq[8] __devinitdata = { 0, };
-static int mem[8] __devinitdata = { 0, };
+static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
+static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
 static char *id __devinitdata = HiSaxID;
 
+#define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"
+
 MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
 MODULE_AUTHOR("Karsten Keil");
 MODULE_LICENSE("GPL");
-MODULE_PARM(type, "1-8i");
-MODULE_PARM(protocol, "1-8i");
-MODULE_PARM(io, "1-8i");
-MODULE_PARM(irq, "1-8i");
-MODULE_PARM(mem, "1-8i");
+MODULE_PARM(type, PARM_PARA);
+MODULE_PARM(protocol, PARM_PARA);
+MODULE_PARM(io, PARM_PARA);
+MODULE_PARM(irq, PARM_PARA);
+MODULE_PARM(mem, PARM_PARA);
 MODULE_PARM(id, "s");
 #ifdef IO0_IO1
-MODULE_PARM(io0, "1-8i");
-MODULE_PARM(io1, "1-8i");
+MODULE_PARM(io0, PARM_PARA);
+MODULE_PARM(io1, PARM_PARA);
 #endif
 #endif /* MODULE */
 
@@ -448,6 +442,7 @@ static int __init HiSax_setup(char *line)
        i = 0;
        j = 1;
        while (argc && (i < HISAX_MAX_CARDS)) {
+               cards[i].protocol = DEFAULT_PROTO;
                if (argc) {
                        cards[i].typ = ints[j];
                        j++;
@@ -475,13 +470,15 @@ static int __init HiSax_setup(char *line)
                }
                i++;
        }
-       if (str && *str) {
-               strcpy(HiSaxID, str);
-               HiSax_id = HiSaxID;
-       } else {
+       if (str && *str) {
+               if (strlen(str) < HISAX_IDSIZE)
+                       strcpy(HiSaxID, str);
+               else
+                       printk(KERN_WARNING "HiSax: ID too long!");
+       } else
                strcpy(HiSaxID, "HiSax");
-               HiSax_id = HiSaxID;
-       }
+
+       HiSax_id = HiSaxID;
        return 1;
 }
 
@@ -1396,6 +1393,8 @@ static int __init HiSax_init(void)
                if (protocol[i]) {
                        cards[j].protocol = protocol[i];
                        nzproto++;
+               } else {
+                       cards[j].protocol = DEFAULT_PROTO;
                }
                switch (type[i]) {
                case ISDN_CTYPE_16_0:
@@ -1473,15 +1472,22 @@ static int __init HiSax_init(void)
                        } else {
                                /* QUADRO is a 4 BRI card */
                                cards[j++].para[0] = 1;
-                               cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
-                               cards[j].protocol = protocol[i];
-                               cards[j++].para[0] = 2;
-                               cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
-                               cards[j].protocol = protocol[i];
-                               cards[j++].para[0] = 3;
-                               cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
-                               cards[j].protocol = protocol[i];
-                               cards[j].para[0] = 4;
+                               /* we need to check if further cards can be added */
+                               if (j < HISAX_MAX_CARDS) {
+                                       cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+                                       cards[j].protocol = protocol[i];
+                                       cards[j++].para[0] = 2;
+                               }
+                               if (j < HISAX_MAX_CARDS) {
+                                       cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+                                       cards[j].protocol = protocol[i];
+                                       cards[j++].para[0] = 3;
+                               }
+                               if (j < HISAX_MAX_CARDS) {
+                                       cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+                                       cards[j].protocol = protocol[i];
+                                       cards[j].para[0] = 4;
+                               }
                        }
                        break;
                }
@@ -1554,6 +1560,8 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
                cards[i].typ = type[i];
                if (protocol[i]) {
                        cards[i].protocol = protocol[i];
+               } else {
+                       cards[i].protocol = DEFAULT_PROTO;
                }
        }
        cards[0].para[0] = pcm_irq;
@@ -1594,6 +1602,8 @@ int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
                cards[i].typ = type[i];
                if (protocol[i]) {
                        cards[i].protocol = protocol[i];
+               } else {
+                       cards[i].protocol = DEFAULT_PROTO;
                }
        }
        cards[0].para[0] = pcm_irq;
@@ -1634,6 +1644,8 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
                cards[i].typ = type[i];
                if (protocol[i]) {
                        cards[i].protocol = protocol[i];
+               } else {
+                       cards[i].protocol = DEFAULT_PROTO;
                }
        }
        cards[0].para[0] = pcm_irq;
@@ -1674,6 +1686,8 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
                cards[i].typ = type[i];
                if (protocol[i]) {
                        cards[i].protocol = protocol[i];
+               } else {
+                       cards[i].protocol = DEFAULT_PROTO;
                }
        }
        cards[0].para[0] = pcm_irq;
index 22a43a93c7a6961a7cea93c8ca433a8aa9a08997..cee7b10a29aa472ae63c977c6555af115c4c0798 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: hisax.h,v 2.52.6.9 2001/09/23 22:24:48 kai Exp $
+/* $Id: hisax.h,v 1.1.4.1.2.1 2001/12/09 20:18:40 kai Exp $
  *
  * Basic declarations, defines and prototypes
  *
@@ -949,8 +949,6 @@ struct IsdnCardState {
 #define  MON0_TX       4
 #define  MON1_TX       8
 
-#define         HISAX_MAX_CARDS        8
-
 #define  ISDN_CTYPE_16_0       1
 #define  ISDN_CTYPE_8_0                2
 #define  ISDN_CTYPE_16_3       3
index a0749e798ce34f1e368fc14f895a66240f16bdab..2e78a0e3d5588427306a6598c7e96e45cc0895e9 100644 (file)
@@ -963,7 +963,7 @@ isdn_info_update(void)
 static ssize_t
 isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
 {
-       uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       uint minor = minor(file->f_dentry->d_inode->i_rdev);
        int len = 0;
        ulong flags;
        int drvidx;
@@ -1077,7 +1077,7 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
 static ssize_t
 isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
 {
-       uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       uint minor = minor(file->f_dentry->d_inode->i_rdev);
        int drvidx;
        int chidx;
        int retval;
@@ -1143,7 +1143,7 @@ static unsigned int
 isdn_poll(struct file *file, poll_table * wait)
 {
        unsigned int mask = 0;
-       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
        int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
 
        lock_kernel();
@@ -1184,7 +1184,7 @@ isdn_poll(struct file *file, poll_table * wait)
 static int
 isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 {
-       uint minor = MINOR(inode->i_rdev);
+       uint minor = minor(inode->i_rdev);
        isdn_ctrl c;
        int drvidx;
        int chidx;
@@ -1635,7 +1635,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 static int
 isdn_open(struct inode *ino, struct file *filep)
 {
-       uint minor = MINOR(ino->i_rdev);
+       uint minor = minor(ino->i_rdev);
        int drvidx;
        int chidx;
        int retval = -ENODEV;
@@ -1696,7 +1696,7 @@ isdn_open(struct inode *ino, struct file *filep)
 static int
 isdn_close(struct inode *ino, struct file *filep)
 {
-       uint minor = MINOR(ino->i_rdev);
+       uint minor = minor(ino->i_rdev);
 
        lock_kernel();
        if (minor == ISDN_MINOR_STATUS) {
index c6ac0a6da25954b7c68175bd9cb1466ad59fd0ea..431683e13627639782fa37c78ff4262c20490038 100644 (file)
@@ -586,7 +586,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
 
        if (is->debug & 0x2)
                printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
-                               MINOR(file->f_dentry->d_inode->i_rdev));
+                               minor(file->f_dentry->d_inode->i_rdev));
 
        /* just registers wait_queue hook. This doesn't really wait. */
        poll_wait(file, &is->wq, wait);
index c73a7d5b1ceab815fbb66143e3faef085ee02649..2f9a7c634ee73aafbe8dbec214b49aa6888a8230 100644 (file)
@@ -1019,12 +1019,12 @@ isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
 #ifdef MODEM_PARANOIA_CHECK
        if (!info) {
                printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n",
-                      MAJOR(device), MINOR(device), routine);
+                      major(device), minor(device), routine);
                return 1;
        }
        if (info->magic != ISDN_ASYNC_MAGIC) {
                printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n",
-                      MAJOR(device), MINOR(device), routine);
+                      major(device), minor(device), routine);
                return 1;
        }
 #endif
@@ -1740,7 +1740,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
        int retval,
         line;
 
-       line = MINOR(tty->device) - tty->driver.minor_start;
+       line = minor(tty->device) - tty->driver.minor_start;
        if (line < 0 || line > ISDN_MAX_CHANNELS)
                return -ENODEV;
        info = &dev->mdm.info[line];
index 85bd3c2cf23c39f480e21d4afc1b5e892be22e38..094ac8224588cba8389b62953b9eb0c8005c8aeb 100644 (file)
@@ -2386,7 +2386,7 @@ static int reset_camera(struct cam_data *cam)
                goto_high_power(cam);
                do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
                if (goto_low_power(cam))
-                       return -NODEV;
+                       return -ENODEV;
        }
        
        /* procedure described in developer's guide p3-28 */
index c6b0e1868d45bbe9c3f242dc8de766236c9438e2..9e1d6e9ba2a2ca219659fab87491ab2df6a23a8f 100644 (file)
@@ -70,7 +70,7 @@ LIST_HEAD(videodev_proc_list);
 static ssize_t video_read(struct file *file,
        char *buf, size_t count, loff_t *ppos)
 {
-       struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+       struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
        if(vfl->read)
                return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
        else
@@ -86,7 +86,7 @@ static ssize_t video_read(struct file *file,
 static ssize_t video_write(struct file *file, const char *buf, 
        size_t count, loff_t *ppos)
 {
-       struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+       struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
        if(vfl->write)
                return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
        else
@@ -100,7 +100,7 @@ static ssize_t video_write(struct file *file, const char *buf,
 
 static unsigned int video_poll(struct file *file, poll_table * wait)
 {
-       struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+       struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
        if(vfl->poll)
                return vfl->poll(vfl, file, wait);
        else
@@ -114,7 +114,7 @@ static unsigned int video_poll(struct file *file, poll_table * wait)
 
 static int video_open(struct inode *inode, struct file *file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        int err, retval = 0;
        struct video_device *vfl;
        
@@ -170,7 +170,7 @@ static int video_release(struct inode *inode, struct file *file)
 {
        struct video_device *vfl;
        lock_kernel();
-       vfl=video_device[MINOR(inode->i_rdev)];
+       vfl=video_device[minor(inode->i_rdev)];
        if(vfl->close)
                vfl->close(vfl);
        vfl->busy=0;
@@ -183,7 +183,7 @@ static int video_release(struct inode *inode, struct file *file)
 static int video_ioctl(struct inode *inode, struct file *file,
        unsigned int cmd, unsigned long arg)
 {
-       struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
+       struct video_device *vfl=video_device[minor(inode->i_rdev)];
        int err=vfl->ioctl(vfl, cmd, (void *)arg);
 
        if(err!=-ENOIOCTLCMD)
@@ -203,7 +203,7 @@ static int video_ioctl(struct inode *inode, struct file *file,
 int video_mmap(struct file *file, struct vm_area_struct *vma)
 {
        int ret = -EINVAL;
-       struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+       struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
        if(vfl->mmap) {
                lock_kernel();
                ret = vfl->mmap(vfl, (char *)vma->vm_start, 
index 15a0ea68c3dabd0ff9d70e05156edfb1782c1555..45ceb740c567704295f9efae580d0c3a1dc63d3b 100644 (file)
@@ -28,8 +28,8 @@
  */
 
 #define DRV_NAME               "de2104x"
-#define DRV_VERSION            "0.5.1"
-#define DRV_RELDATE            "Nov 20, 2001"
+#define DRV_VERSION            "0.5.4"
+#define DRV_RELDATE            "Jan 1, 2002"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -45,6 +45,7 @@
 #include <linux/rtnetlink.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
+#include <asm/unaligned.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __initdata =
@@ -99,6 +100,7 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
 #define DE_DUMMY_SKB           ((struct sk_buff *) 2)
 #define DE_SETUP_FRAME_WORDS   96
 #define DE_EEPROM_WORDS                256
+#define DE_EEPROM_SIZE         (DE_EEPROM_WORDS * sizeof(u16))
 #define DE_MAX_MEDIA           5
 
 #define DE_MEDIA_TP_AUTO       0
@@ -109,6 +111,8 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
 #define DE_MEDIA_INVALID       DE_MAX_MEDIA
 #define DE_MEDIA_FIRST         0
 #define DE_MEDIA_LAST          (DE_MAX_MEDIA - 1)
+#define DE_AUI_BNC             (SUPPORTED_AUI | SUPPORTED_BNC)
+
 #define DE_TIMER_LINK          (60 * HZ)
 #define DE_TIMER_NO_LINK       (5 * HZ)
 
@@ -117,7 +121,9 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
 #define DE_REGS_VER            1
 
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (6*HZ)
+#define TX_TIMEOUT             (6*HZ)
+
+#define DE_UNALIGNED_16(a)     (u16)(get_unaligned((u16 *)(a)))
 
 /* This is a mysterious value that can be written to CSR11 in the 21040 (only)
    to support a pre-NWay full-duplex signaling mechanism using short frames.
@@ -254,7 +260,6 @@ struct de_srom_info_leaf {
        u16                     default_media;
        u8                      n_blocks;
        u8                      unused;
-       struct de_srom_media_block      media[0];
 } __attribute__((packed));
 
 struct de_desc {
@@ -307,6 +312,7 @@ struct de_private {
        struct media_info       media[DE_MAX_MEDIA];
        struct timer_list       media_timer;
 
+       u8                      *ee_data;
        unsigned                board_idx;
        unsigned                de21040 : 1;
        unsigned                media_lock : 1;
@@ -319,6 +325,7 @@ static void de_clean_rings (struct de_private *de);
 static void de_media_interrupt (struct de_private *de, u32 status);
 static void de21040_media_timer (unsigned long data);
 static void de21041_media_timer (unsigned long data);
+static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media);
 
 
 static struct pci_device_id de_pci_tbl[] __initdata = {
@@ -918,7 +925,6 @@ static void de_stop_hw (struct de_private *de)
 
        dw32(MacStatus, dr32(MacStatus));
 
-       synchronize_irq();
        udelay(10);
 
        de->rx_tail = 0;
@@ -968,15 +974,29 @@ static void de_set_media (struct de_private *de)
        else
                de->macmode &= ~FullDuplex;
        
-       if (netif_msg_link(de))
-               printk(KERN_INFO "%s: set link %s, mode %x, sia %x,%x,%x,%x\n"
-                      KERN_INFO "                 set mode %x, set sia %x,%x,%x\n",
+       if (netif_msg_link(de)) {
+               printk(KERN_INFO "%s: set link %s\n"
+                      KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
+                      KERN_INFO "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
                       de->dev->name, media_name[media],
-                      dr32(MacMode), dr32(SIAStatus), dr32(CSR13),
-                      dr32(CSR14), dr32(CSR15), de->macmode,
-                       de->media[media].csr13,
-                       de->media[media].csr14,
-                       de->media[media].csr15);
+                      de->dev->name, dr32(MacMode), dr32(SIAStatus),
+                      dr32(CSR13), dr32(CSR14), dr32(CSR15),
+                      de->dev->name, de->macmode, de->media[media].csr13,
+                      de->media[media].csr14, de->media[media].csr15);
+       }
+}
+
+static void de_next_media (struct de_private *de, u32 *media,
+                          unsigned int n_media)
+{
+       unsigned int i;
+
+       for (i = 0; i < n_media; i++) {
+               if (de_ok_to_advertise(de, media[i])) {
+                       de->media_type = media[i];
+                       return;
+               }
+       }
 }
 
 static void de21040_media_timer (unsigned long data)
@@ -985,6 +1005,7 @@ static void de21040_media_timer (unsigned long data)
        struct net_device *dev = de->dev;
        u32 status = dr32(SIAStatus);
        unsigned int carrier;
+       unsigned long flags;
        
        carrier = (status & NetCxnErr) ? 0 : 1;
                
@@ -1009,12 +1030,17 @@ static void de21040_media_timer (unsigned long data)
        if (de->media_lock)
                return;
 
-       if (de->media_type == DE_MEDIA_AUI)
-               de->media_type = DE_MEDIA_TP;
-       else
-               de->media_type = DE_MEDIA_AUI;
+       if (de->media_type == DE_MEDIA_AUI) {
+               u32 next_state = DE_MEDIA_TP;
+               de_next_media(de, &next_state, 1);
+       } else {
+               u32 next_state = DE_MEDIA_AUI;
+               de_next_media(de, &next_state, 1);
+       }
 
+       spin_lock_irqsave(&de->lock, flags);
        de_stop_rxtx(de);
+       spin_unlock_irqrestore(&de->lock, flags);
        de_set_media(de);
        de_start_rxtx(de);
 
@@ -1061,8 +1087,9 @@ static void de21041_media_timer (unsigned long data)
 {
        struct de_private *de = (struct de_private *) data;
        struct net_device *dev = de->dev;
-       u32 status = dr32(SIAStatus), new_media;
+       u32 status = dr32(SIAStatus);
        unsigned int carrier;
+       unsigned long flags;
        
        carrier = (status & NetCxnErr) ? 0 : 1;
                
@@ -1093,27 +1120,55 @@ static void de21041_media_timer (unsigned long data)
 
        /* if activity detected, use that as hint for new media type */
        if (status & NonselPortActive) {
-               if (de->media_type == DE_MEDIA_AUI)
-                       de->media_type = DE_MEDIA_TP;
-               else
+               unsigned int have_media = 1;
+
+               /* if AUI/BNC selected, then activity is on TP port */
+               if (de->media_type == DE_MEDIA_AUI ||
+                   de->media_type == DE_MEDIA_BNC) {
+                       if (de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))
+                               de->media_type = DE_MEDIA_TP_AUTO;
+                       else
+                               have_media = 0;
+               }
+
+               /* TP selected.  If there is only TP and BNC, then it's BNC */
+               else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_BNC) &&
+                        de_ok_to_advertise(de, DE_MEDIA_BNC))
+                       de->media_type = DE_MEDIA_BNC;
+
+               /* TP selected.  If there is only TP and AUI, then it's AUI */
+               else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_AUI) &&
+                        de_ok_to_advertise(de, DE_MEDIA_AUI))
                        de->media_type = DE_MEDIA_AUI;
-               goto set_media;
-       }
 
-       /* move to next advertised media */
-       new_media = de->media_type;
-       do {
-               if (new_media == DE_MEDIA_LAST)
-                       new_media = DE_MEDIA_FIRST;
+               /* otherwise, ignore the hint */
                else
-                       new_media++;
-       } while ((!de_ok_to_advertise(de, new_media)) &&
-                (new_media != de->media_type));
+                       have_media = 0;
 
-       de->media_type = new_media;
+               if (have_media)
+                       goto set_media;
+       }
+
+       /*
+        * Absent or ambiguous activity hint, move to next advertised
+        * media state.  If de->media_type is left unchanged, this
+        * simply resets the PHY and reloads the current media settings.
+        */
+       if (de->media_type == DE_MEDIA_AUI) {
+               u32 next_states[] = { DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+               de_next_media(de, next_states, ARRAY_SIZE(next_states));
+       } else if (de->media_type == DE_MEDIA_BNC) {
+               u32 next_states[] = { DE_MEDIA_TP_AUTO, DE_MEDIA_AUI };
+               de_next_media(de, next_states, ARRAY_SIZE(next_states));
+       } else {
+               u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+               de_next_media(de, next_states, ARRAY_SIZE(next_states));
+       }
        
 set_media:
+       spin_lock_irqsave(&de->lock, flags);
        de_stop_rxtx(de);
+       spin_unlock_irqrestore(&de->lock, flags);
        de_set_media(de);
        de_start_rxtx(de);
 
@@ -1145,20 +1200,21 @@ static void de_media_interrupt (struct de_private *de, u32 status)
 
 static int de_reset_mac (struct de_private *de)
 {
-       unsigned tmp;
-       u32 status;
+       u32 status, tmp;
 
        /*
         * Reset MAC.  Copied from de4x5.c.
         */
 
-       dr32 (BusMode);
+       tmp = dr32 (BusMode);
+       if (tmp == 0xffffffff)
+               return -ENODEV;
        mdelay (1);
 
-       dw32 (BusMode, de_bus_mode | CmdReset);
+       dw32 (BusMode, tmp | CmdReset);
        mdelay (1);
 
-       dw32 (BusMode, de_bus_mode);
+       dw32 (BusMode, tmp);
        mdelay (1);
 
        for (tmp = 0; tmp < 5; tmp++) {
@@ -1309,12 +1365,20 @@ static void de_clean_rings (struct de_private *de)
        }
 
        for (i = 0; i < DE_TX_RING_SIZE; i++) {
-               if (de->tx_skb[i].skb) {
-                       struct sk_buff *skb = de->tx_skb[i].skb;
-                       pci_unmap_single(de->pdev, de->tx_skb[i].mapping,
-                                        skb->len, PCI_DMA_TODEVICE);
-                       dev_kfree_skb(skb);
-                       de->net_stats.tx_dropped++;
+               struct sk_buff *skb = de->tx_skb[i].skb;
+               if ((skb) && (skb != DE_DUMMY_SKB)) {
+                       if (skb != DE_SETUP_SKB) {
+                               dev_kfree_skb(skb);
+                               de->net_stats.tx_dropped++;
+                               pci_unmap_single(de->pdev,
+                                       de->tx_skb[i].mapping,
+                                       skb->len, PCI_DMA_TODEVICE);
+                       } else {
+                               pci_unmap_single(de->pdev,
+                                       de->tx_skb[i].mapping,
+                                       sizeof(de->setup_frame),
+                                       PCI_DMA_TODEVICE);
+                       }
                }
        }
 
@@ -1334,6 +1398,7 @@ static int de_open (struct net_device *dev)
 {
        struct de_private *de = dev->priv;
        int rc;
+       unsigned long flags;
 
        if (netif_msg_ifup(de))
                printk(KERN_DEBUG "%s: enabling interface\n", dev->name);
@@ -1362,11 +1427,15 @@ static int de_open (struct net_device *dev)
        }
 
        netif_start_queue(dev);
+       mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
 
        return 0;
 
 err_out_hw:
+       spin_lock_irqsave(&de->lock, flags);
        de_stop_hw(de);
+       spin_unlock_irqrestore(&de->lock, flags);
+
 err_out_free:
        de_free_rings(de);
        return rc;
@@ -1375,15 +1444,21 @@ err_out_free:
 static int de_close (struct net_device *dev)
 {
        struct de_private *de = dev->priv;
+       unsigned long flags;
 
        if (netif_msg_ifdown(de))
                printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
-       netif_stop_queue(dev);
-       netif_carrier_off(dev);
        del_timer_sync(&de->media_timer);
+
+       spin_lock_irqsave(&de->lock, flags);
        de_stop_hw(de);
+       netif_stop_queue(dev);
+       netif_carrier_off(dev);
+       spin_unlock_irqrestore(&de->lock, flags);
+       
        free_irq(dev->irq, dev);
+
        de_free_rings(de);
        de_adapter_sleep(de);
        pci_disable_device(de->pdev);
@@ -1558,6 +1633,7 @@ static int de_ethtool_ioctl (struct de_private *de, void *useraddr)
                strcpy (info.driver, DRV_NAME);
                strcpy (info.version, DRV_VERSION);
                strcpy (info.bus_info, de->pdev->slot_name);
+               info.eedump_len = DE_EEPROM_SIZE;
                info.regdump_len = DE_REGS_SIZE;
                if (copy_to_user (useraddr, &info, sizeof (info)))
                        return -EFAULT;
@@ -1658,6 +1734,23 @@ static int de_ethtool_ioctl (struct de_private *de, void *useraddr)
                return 0;
        }
 
+       /* get SROM dump */
+       case ETHTOOL_GEEPROM: {
+               struct ethtool_eeprom eeprom;
+
+               if (!de->ee_data)
+                       break;
+               if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+                       return -EFAULT;
+               if ((eeprom.offset != 0) || (eeprom.magic != 0) ||
+                   (eeprom.len != DE_EEPROM_SIZE))
+                       return -EINVAL;
+
+               useraddr += offsetof(struct ethtool_regs, data);
+               if (copy_to_user(useraddr, de->ee_data, DE_EEPROM_SIZE))
+                       return -EFAULT;
+       }
+
        default:
                break;
        }
@@ -1703,7 +1796,31 @@ static void __init de21040_get_mac_address (struct de_private *de)
        }
 }
 
-/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
+static void __init de21040_get_media_info(struct de_private *de)
+{
+       unsigned int i;
+
+       de->media_type = DE_MEDIA_TP;
+       de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
+                              SUPPORTED_10baseT_Half | SUPPORTED_AUI;
+       de->media_advertise = de->media_supported;
+
+       for (i = 0; i < DE_MAX_MEDIA; i++) {
+               switch (i) {
+               case DE_MEDIA_AUI:
+               case DE_MEDIA_TP:
+               case DE_MEDIA_TP_FD:
+                       de->media[i].type = i;
+                       de->media[i].csr13 = t21040_csr13[i];
+                       de->media[i].csr14 = t21040_csr14[i];
+                       de->media[i].csr15 = t21040_csr15[i];
+                       break;
+               default:
+                       de->media[i].type = DE_MEDIA_INVALID;
+                       break;
+               }
+       }
+}
 
 /* Note: this routine returns extra data bits for size detection. */
 static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len)
@@ -1741,15 +1858,16 @@ static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len)
        return retval;
 }
 
-static void __init tulip_get_srom_info (struct de_private *de)
+static void __init de21041_get_srom_info (struct de_private *de)
 {
        unsigned i, sa_offset = 0, ofs;
-       u8 ee_data[DE_EEPROM_WORDS * sizeof(u16)];
+       u8 ee_data[DE_EEPROM_SIZE + 6] = {};
        unsigned ee_addr_size = tulip_read_eeprom(de->regs, 0xff, 8) & 0x40000 ? 8 : 6;
        struct de_srom_info_leaf *il;
+       void *bufp;
 
        /* download entire eeprom */
-       for (i = 0; i < sizeof(ee_data)/2; i++)
+       for (i = 0; i < DE_EEPROM_WORDS; i++)
                ((u16 *)ee_data)[i] =
                        le16_to_cpu(tulip_read_eeprom(de->regs, i, ee_addr_size));
 
@@ -1780,13 +1898,18 @@ static void __init tulip_get_srom_info (struct de_private *de)
                goto bad_srom;
 
        /* get default media type */
-       switch (il->default_media) {
+       switch (DE_UNALIGNED_16(&il->default_media)) {
        case 0x0001:  de->media_type = DE_MEDIA_BNC; break;
        case 0x0002:  de->media_type = DE_MEDIA_AUI; break;
        case 0x0204:  de->media_type = DE_MEDIA_TP_FD; break;
        default: de->media_type = DE_MEDIA_TP_AUTO; break;
        }
        
+       if (netif_msg_probe(de))
+               printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n",
+                      de->board_idx, ofs,
+                      media_name[de->media_type]);
+
        /* init SIA register values to defaults */
        for (i = 0; i < DE_MAX_MEDIA; i++) {
                de->media[i].type = DE_MEDIA_INVALID;
@@ -1798,8 +1921,9 @@ static void __init tulip_get_srom_info (struct de_private *de)
        /* parse media blocks to see what medias are supported,
         * and if any custom CSR values are provided
         */
+       bufp = ((void *)il) + sizeof(*il);
        for (i = 0; i < il->n_blocks; i++) {
-               struct de_srom_media_block *ib = &il[i].media[0];
+               struct de_srom_media_block *ib = bufp;
                unsigned idx;
 
                /* index based on media type in media block */
@@ -1828,16 +1952,37 @@ static void __init tulip_get_srom_info (struct de_private *de)
                        goto bad_srom;
                }
 
-               if (ib->opts & MediaCustomCSRs) {
-                       de->media[idx].csr13 = ib->csr13;
-                       de->media[idx].csr14 = ib->csr14;
-                       de->media[idx].csr15 = ib->csr15;
-               }
-
                de->media[idx].type = idx;
-               de->media_advertise |= de->media_supported;
+
+               if (netif_msg_probe(de))
+                       printk(KERN_INFO "de%d:   media block #%u: %s",
+                              de->board_idx, i,
+                              media_name[de->media[idx].type]);
+
+               bufp += sizeof (ib->opts);
+
+               if (ib->opts & MediaCustomCSRs) {
+                       de->media[idx].csr13 = DE_UNALIGNED_16(&ib->csr13);
+                       de->media[idx].csr14 = DE_UNALIGNED_16(&ib->csr14);
+                       de->media[idx].csr15 = DE_UNALIGNED_16(&ib->csr15);
+                       bufp += sizeof(ib->csr13) + sizeof(ib->csr14) +
+                               sizeof(ib->csr15);
+
+                       if (netif_msg_probe(de))
+                               printk(" (%x,%x,%x)\n",
+                                      de->media[idx].csr13,
+                                      de->media[idx].csr14,
+                                      de->media[idx].csr15);
+                                      
+               } else if (netif_msg_probe(de))
+                       printk("\n");
+
+               if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3]))
+                       break;
        }
 
+       de->media_advertise = de->media_supported;
+
 fill_defaults:
        /* fill in defaults, for cases where custom CSRs not used */
        for (i = 0; i < DE_MAX_MEDIA; i++) {
@@ -1849,12 +1994,9 @@ fill_defaults:
                        de->media[i].csr15 = t21041_csr15[i];
        }
 
-       if (netif_msg_link(de))
-               printk(KERN_INFO "de%d: SROM-listed ports: %s%s%s\n",
-                      de->board_idx,
-                      de->media_supported & SUPPORTED_TP ? "TP " : "",
-                      de->media_supported & SUPPORTED_BNC ? "BNC " : "",
-                      de->media_supported & SUPPORTED_AUI ? "AUI" : "");
+       de->ee_data = kmalloc(DE_EEPROM_SIZE, GFP_KERNEL);
+       if (de->ee_data)
+               memcpy(de->ee_data, &ee_data[0], DE_EEPROM_SIZE);
 
        return;
 
@@ -1970,35 +2112,21 @@ static int __init de_init_one (struct pci_dev *pdev,
        de_adapter_wake(de);
 
        /* make sure hardware is not running */
-       de_stop_hw(de);
+       rc = de_reset_mac(de);
+       if (rc) {
+               printk(KERN_ERR PFX "Cannot reset MAC, pci dev %s\n",
+                      pdev->slot_name);
+               goto err_out_iomap;
+       }
 
-       /* get MAC address, and some register values related to media types */
+       /* get MAC address, initialize default media type and
+        * get list of supported media
+        */
        if (de->de21040) {
-               unsigned i;
-               
                de21040_get_mac_address(de);
-
-               de->media_type = DE_MEDIA_TP;
-               de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
-                                 SUPPORTED_10baseT_Half | SUPPORTED_AUI;
-               de->media_advertise = de->media_supported;
-               for (i = 0; i < DE_MAX_MEDIA; i++) {
-                       switch (i) {
-                       case DE_MEDIA_AUI:
-                       case DE_MEDIA_TP:
-                       case DE_MEDIA_TP_FD:
-                               de->media[i].type = i;
-                               de->media[i].csr13 = t21040_csr13[i];
-                               de->media[i].csr14 = t21040_csr14[i];
-                               de->media[i].csr15 = t21040_csr15[i];
-                               break;
-                       default:
-                               de->media[i].type = DE_MEDIA_INVALID;
-                               break;
-                       }
-               }
+               de21040_get_media_info(de);
        } else {
-               tulip_get_srom_info(de);
+               de21041_get_srom_info(de);
        }
 
        /* register new network interface with kernel */
@@ -2029,6 +2157,8 @@ static int __init de_init_one (struct pci_dev *pdev,
        return 0;
 
 err_out_iomap:
+       if (de->ee_data)
+               kfree(de->ee_data);
        iounmap(regs);
 err_out_res:
        pci_release_regions(pdev);
@@ -2047,6 +2177,8 @@ static void __exit de_remove_one (struct pci_dev *pdev)
        if (!dev)
                BUG();
        unregister_netdev(dev);
+       if (de->ee_data)
+               kfree(de->ee_data);
        iounmap(de->regs);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
index 177dbed4ee1b85a99d7a4023184b526763a89a00..c9f5f7f425c1150ccad9f47ac5d525847c4dd20b 100644 (file)
@@ -500,7 +500,7 @@ static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_
 
 static int __init dfx_eisa_init(void)
 {
-       int rc = -NODEV;
+       int rc = -ENODEV;
        int i;                  /* used in for loops */
        u16 port;               /* temporary I/O (port) address */
        u32 slot_id;            /* EISA hardware (slot) ID read from adapter */
index 63d5a5557a11dae05c694fcb2d8d1c39c5726f01..cb9110e112a44e9846a5838eb8f5ae850b29be64 100644 (file)
@@ -172,7 +172,7 @@ static int irtty_open(struct tty_struct *tty)
 
        /* Give self a name */
        sprintf(name, "%s%d", tty->driver.name,
-               MINOR(tty->device) - tty->driver.minor_start +
+               minor(tty->device) - tty->driver.minor_start +
                tty->driver.name_base);
 
        hashbin_insert(irtty, (irda_queue_t *) self, (int) self, NULL);
@@ -910,7 +910,7 @@ static int irtty_net_open(struct net_device *dev)
 
        /* Give self a hardware name */
        sprintf(hwname, "%s%d", tty->driver.name,
-               MINOR(tty->device) - tty->driver.minor_start +
+               minor(tty->device) - tty->driver.minor_start +
                tty->driver.name_base);
 
        /* 
index 8e44201e6662def6462c2a78ea5d9a412144f379..d59f79cb85440de2aced4df3978eccfb561cc5f9 100644 (file)
@@ -739,7 +739,7 @@ sl_alloc(kdev_t line)
                        break;
 
                if (slp->ctrl.leased) {
-                       if (slp->ctrl.line != line)
+                       if (!kdev_same(slp->ctrl.line, line))
                                continue;
                        if (slp->ctrl.tty)
                                return NULL;
@@ -753,7 +753,7 @@ sl_alloc(kdev_t line)
                        continue;
 
                if (current->pid == slp->ctrl.pid) {
-                       if (slp->ctrl.line == line && score < 3) {
+                       if (kdev_same(slp->ctrl.line, line) && score < 3) {
                                sel = i;
                                score = 3;
                                continue;
@@ -764,7 +764,7 @@ sl_alloc(kdev_t line)
                        }
                        continue;
                }
-               if (slp->ctrl.line == line && score < 1) {
+               if (kdev_same(slp->ctrl.line, line) && score < 1) {
                        sel = i;
                        score = 1;
                        continue;
@@ -944,7 +944,7 @@ slip_close(struct tty_struct *tty)
        tty->disc_data = 0;
        sl->tty = NULL;
        if (!sl->leased)
-               sl->line = 0;
+               sl->line = NODEV;
 
        /* VSV = very important to remove timers */
 #ifdef CONFIG_SLIP_SMART
index 2b1a79a9100fca8d05c7cc50aed5731af2987262..883d064de3ec3c5fe6856ac5f6b8e0c3658902a7 100644 (file)
@@ -940,12 +940,12 @@ static int cosa_open(struct inode *inode, struct file *file)
        unsigned long flags;
        int n;
 
-       if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
+       if ((n=minor(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
                >= nr_cards)
                return -ENODEV;
        cosa = cosa_cards+n;
 
-       if ((n=MINOR(file->f_dentry->d_inode->i_rdev)
+       if ((n=minor(file->f_dentry->d_inode->i_rdev)
                & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
                return -ENODEV;
        chan = cosa->chan + n;
index f3a574fe356cf5a06da4d196f138be875bb11a0c..2810ab8e57a6992cbc83a9f59c89f2da9c66819f 100644 (file)
@@ -3933,7 +3933,7 @@ static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp)
        
        if (!tty->driver_data){
                int port;
-               port = MINOR(tty->device) - tty->driver.minor_start;
+               port = minor(tty->device) - tty->driver.minor_start;
                if ((port < 0) || (port >= NR_PORTS)) 
                        return -ENODEV;
                
index 8ec1d1391527cb7dc8a22829d7e837605ced32c2..b0c7bd184f98cf0ad6dbcf88ab9528e5dec61834 100644 (file)
@@ -1531,7 +1531,7 @@ static inline
 void BusLogic_AcquireHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
                                       ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+  spin_lock_irqsave(&HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1544,7 +1544,7 @@ static inline
 void BusLogic_ReleaseHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
                                       ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
index 080847a4ec46d9ec10107e75db43d66ead03d164..85a91217a57de5147c57d1932da796b8a53483a3 100644 (file)
@@ -3610,36 +3610,6 @@ typedef struct {
 #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif /* CONFIG_PROC_FS */
 
-/*
- * XXX - Release and acquire the io_request_lock. These macros are needed
- * because the 2.4 kernel SCSI mid-level driver holds the 'io_request_lock'
- * on entry to SCSI low-level drivers.
- *
- * These definitions and all code that uses code should be removed when the
- * SCSI mid-level driver no longer holds the 'io_request_lock' on entry to
- * SCSI low-level driver detect, queuecommand, and reset entrypoints.
- *
- * The interrupt flags values doesn't matter in the macros because the
- * SCSI mid-level will save and restore the flags values before and after
- * calling advansys_detect, advansys_queuecommand, and advansys_reset where
- * these macros are used. We do want interrupts enabled after the lock is
- * released so an explicit sti() is done. The driver only needs interrupts
- * disabled when it acquires the per board lock.
- */
-#define ASC_UNLOCK_IO_REQUEST_LOCK \
-    { \
-        ulong flags; /* flags value not needed, cf. comment above. */ \
-        save_flags(flags); \
-        spin_unlock_irqrestore(&io_request_lock, flags); \
-        sti(); /* enable interrupts */ \
-    }
-
-#define ASC_LOCK_IO_REQUEST_LOCK \
-    { \
-        ulong flags; /* flags value not needed, cf. comment above. */ \
-        spin_lock_irqsave(&io_request_lock, flags); \
-    }
-
 /* Asc Library return codes */
 #define ASC_TRUE        1
 #define ASC_FALSE       0
@@ -4084,7 +4054,6 @@ typedef struct asc_board {
         ADVEEP_38C1600_CONFIG adv_38C1600_eep;  /* 38C1600 EEPROM config. */
     } eep_config;
     ulong                last_reset;            /* Saved last reset time */
-    spinlock_t lock;                            /* Board spinlock */
 #ifdef CONFIG_PROC_FS
     /* /proc/scsi/advansys/[0...] */
     char                 *prtbuf;               /* /proc print buffer */
@@ -4604,13 +4573,6 @@ advansys_detect(Scsi_Host_Template *tpnt)
 
     ASC_DBG(1, "advansys_detect: begin\n");
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level detect entrypoint.
-     */
-    ASC_UNLOCK_IO_REQUEST_LOCK
-
 #if ASC_LINUX_KERNEL24
     tpnt->proc_name = "advansys";
 #elif ASC_LINUX_KERNEL22
@@ -4837,9 +4799,6 @@ advansys_detect(Scsi_Host_Template *tpnt)
             memset(boardp, 0, sizeof(asc_board_t));
             boardp->id = asc_board_count - 1;
 
-            /* Initialize spinlock. */
-            boardp->lock = SPIN_LOCK_UNLOCKED;
-
             /*
              * Handle both narrow and wide boards.
              *
@@ -5723,13 +5682,6 @@ advansys_detect(Scsi_Host_Template *tpnt)
         }
     }
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level detect entrypoint.
-     */
-    ASC_LOCK_IO_REQUEST_LOCK
-
     ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
     return asc_board_count;
 }
@@ -5893,14 +5845,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
     boardp = ASC_BOARDP(shp);
     ASC_STATS(shp, queuecommand);
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level queuecommand entrypoint.
-     */
-    ASC_UNLOCK_IO_REQUEST_LOCK
-
-    spin_lock_irqsave(&boardp->lock, flags);
+    spin_lock_irqsave(&shp->host_lock, flags);
 
     /*
      * Block new commands while handling a reset or abort request.
@@ -5917,7 +5862,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
          * handling.
          */
         asc_enqueue(&boardp->done, scp, ASC_BACK);
-        spin_unlock_irqrestore(&boardp->lock, flags);
+        spin_unlock_irqrestore(&shp->host_lock, flags);
         return 0;
     }
 
@@ -5961,15 +5906,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
         break;
     }
 
-    spin_unlock_irqrestore(&boardp->lock, flags);
-
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level queuecommand entrypoint.
-     */
-    ASC_LOCK_IO_REQUEST_LOCK
-
+    spin_unlock_irqrestore(&shp->host_lock, flags);
     return 0;
 }
 
@@ -6015,20 +5952,13 @@ advansys_reset(Scsi_Cmnd *scp)
     /*
      * Check for re-entrancy.
      */
-    spin_lock_irqsave(&boardp->lock, flags);
+    spin_lock_irqsave(&shp->host_lock, flags);
     if (boardp->flags & ASC_HOST_IN_RESET) {
-        spin_unlock_irqrestore(&boardp->lock, flags);
+        spin_unlock_irqrestore(&shp->host_lock, flags);
         return FAILED;
     }
     boardp->flags |= ASC_HOST_IN_RESET;
-    spin_unlock_irqrestore(&boardp->lock, flags);
-
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level reset entrypoint.
-     */
-    ASC_UNLOCK_IO_REQUEST_LOCK
+    spin_unlock_irqrestore(&shp->host_lock, flags);
 
     if (ASC_NARROW_BOARD(boardp)) {
         /*
@@ -6063,7 +5993,7 @@ advansys_reset(Scsi_Cmnd *scp)
         /*
          * Acquire the board lock.
          */
-        spin_lock_irqsave(&boardp->lock, flags);
+        spin_lock_irqsave(&shp->host_lock, flags);
 
     } else {
         /*
@@ -6094,7 +6024,7 @@ advansys_reset(Scsi_Cmnd *scp)
          * Acquire the board lock and ensure all requests completed by the
          * microcode have been processed by calling AdvISR().
          */
-        spin_lock_irqsave(&boardp->lock, flags);
+        spin_lock_irqsave(&shp->host_lock, flags);
         (void) AdvISR(adv_dvc_varp);
     }
 
@@ -6160,7 +6090,7 @@ advansys_reset(Scsi_Cmnd *scp)
     boardp->flags &= ~ASC_HOST_IN_RESET;
 
     /* Release the board. */
-    spin_unlock_irqrestore(&boardp->lock, flags);
+    spin_unlock_irqrestore(&shp->host_lock, flags);
 
     /*
      * Complete all the 'done_scp' requests.
@@ -6169,13 +6099,6 @@ advansys_reset(Scsi_Cmnd *scp)
         asc_scsi_done_list(done_scp);
     }
 
-    /*
-     * XXX - Remove this comment and the next line when SCSI mid-level
-     * no longer acquires 'io_request_lock' before calling the SCSI
-     * low-level reset entrypoint.
-     */
-    ASC_LOCK_IO_REQUEST_LOCK
-
     ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
 
     return ret;
@@ -6344,10 +6267,11 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
      * AscISR() will call asc_isr_callback().
      */
     for (i = 0; i < asc_board_count; i++) {
-        boardp = ASC_BOARDP(asc_host[i]);
+       struct Scsi_Host *shp = asc_host[i];
+        boardp = ASC_BOARDP(shp);
         ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
             i, (ulong) boardp);
-        spin_lock_irqsave(&boardp->lock, flags);
+        spin_lock_irqsave(&shp->host_lock, flags);
         if (ASC_NARROW_BOARD(boardp)) {
             /*
              * Narrow Board
@@ -6403,7 +6327,7 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                 }
             }
         }
-        spin_unlock_irqrestore(&boardp->lock, flags);
+        spin_unlock_irqrestore(&shp->host_lock, flags);
     }
 
     /*
index 36f38350fd62e79d520106e7ebe93523e5bf4287..938019b6654fa418ca8b6009faa08a30b325e38f 100644 (file)
@@ -1349,9 +1349,9 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
 
                printk(KERN_INFO "aha152x%d: trying software interrupt, ", HOSTNO);
                SETPORT(DMACNTRL0, SWINT|INTEN);
-               spin_unlock_irq(&io_request_lock);
+               spin_unlock_irq(&shpnt->host_lock);
                mdelay(1000);
-               spin_lock_irq(&io_request_lock);
+               spin_lock_irq(&shpnt->host_lock);
                free_irq(shpnt->irq, shpnt);
 
                if (!HOSTDATA(shpnt)->swint) {
index 8e2609ab33e95ca21d7b9e477b5be7e686aff147..63805aec9c302b8ae594440bea4d6b47fcc50d41 100644 (file)
@@ -213,6 +213,7 @@ int aha1740_test_port(unsigned int base)
 /* A "high" level interrupt handler */
 void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
 {
+    struct Scsi_Host *host = aha_host[irq - 9];
     void (*my_done)(Scsi_Cmnd *);
     int errstatus, adapstat;
     int number_serviced;
@@ -221,11 +222,10 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
     unsigned int base;
     unsigned long flags;
 
-    spin_lock_irqsave(&io_request_lock, flags);
-
-    if (!aha_host[irq - 9])
+    if (!host)
        panic("aha1740.c: Irq from unknown host!\n");
-    base = aha_host[irq - 9]->io_port;
+    spin_lock_irqsave(&host->host_lock, flags);
+    base = host->io_port;
     number_serviced = 0;
 
     while(inb(G2STAT(base)) & G2STAT_INTPEND)
@@ -299,7 +299,7 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
        number_serviced++;
     }
 
-    spin_unlock_irqrestore(&io_request_lock, flags);
+    spin_unlock_irqrestore(&host->host_lock, flags);
 }
 
 int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
index db4e6c8a10434ac36d6cea1633de114149ca349c..cdde0295cd3ea8efaa98ac03d1f79f3e26c2e2ca 100644 (file)
@@ -1157,17 +1157,13 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
        msg[2] |= 0x80000000 | ((u32)wait_data->id);
        timeout *= HZ;
        if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
-               if(!timeout){
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       spin_unlock_irq(&io_request_lock);
+               set_current_state(TASK_INTERRUPTIBLE);
+               spin_unlock_irq(&pHba->host->host_lock);
+               if (!timeout)
                        schedule();
-                       spin_lock_irq(&io_request_lock);
-               } else {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       spin_unlock_irq(&io_request_lock);
+               else
                        schedule_timeout(timeout*HZ);
-                       spin_lock_irq(&io_request_lock);
-               }
+               spin_lock_irq(&pHba->host->host_lock);
        }
        wq_write_lock_irq(&adpt_wq_i2o_post.lock);
        __remove_wait_queue(&adpt_wq_i2o_post, &wait);
@@ -1560,7 +1556,7 @@ static int adpt_open(struct inode *inode, struct file *file)
 
        //TODO check for root access
        //
-       minor = MINOR(inode->i_rdev);
+       minor = minor(inode->i_rdev);
        if (minor >= hba_count) {
                return -ENXIO;
        }
@@ -1591,7 +1587,7 @@ static int adpt_close(struct inode *inode, struct file *file)
        int minor;
        adpt_hba* pHba;
 
-       minor = MINOR(inode->i_rdev);
+       minor = minor(inode->i_rdev);
        if (minor >= hba_count) {
                return -ENXIO;
        }
@@ -1705,7 +1701,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32* arg)
        }
 
        do {
-               spin_lock_irqsave(&io_request_lock, flags);
+               spin_lock_irqsave(&pHba->host->host_lock, flags);
                // This state stops any new commands from enterring the
                // controller while processing the ioctl
 //             pHba->state |= DPTI_STATE_IOCTL;
@@ -1713,7 +1709,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32* arg)
 //             the queue empties and stops.  We need a way to restart the queue
                rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
 //             pHba->state &= ~DPTI_STATE_IOCTL;
-               spin_unlock_irqrestore(&io_request_lock, flags);
+               spin_unlock_irqrestore(&pHba->host->host_lock, flags);
        } while(rcode == -ETIMEDOUT);  
 
        if(rcode){
@@ -1887,7 +1883,7 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
        adpt_hba* pHba;
        ulong flags;
 
-       minor = MINOR(inode->i_rdev);
+       minor = minor(inode->i_rdev);
        if (minor >= DPTI_MAX_HBA){
                return -ENXIO;
        }
@@ -1951,9 +1947,9 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
                break;
                }
        case I2ORESETCMD:
-               spin_lock_irqsave(&io_request_lock, flags);
+               spin_lock_irqsave(&pHba->host->host_lock, flags);
                adpt_hba_reset(pHba);
-               spin_unlock_irqrestore(&io_request_lock, flags);
+               spin_unlock_irqrestore(&pHba->host->host_lock, flags);
                break;
        case I2ORESCANCMD:
                adpt_rescan(pHba);
@@ -1989,19 +1985,18 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
 static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
        Scsi_Cmnd* cmd;
-       adpt_hba* pHba=NULL;
+       adpt_hba* pHba = dev_id;
        u32 m;
        ulong reply;
        u32 status=0;
        u32 context;
        ulong flags = 0;
 
-       pHba = dev_id;
        if (pHba == NULL ){
                printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
                return;
        }
-       spin_lock_irqsave(&io_request_lock, flags);
+       spin_lock_irqsave(&pHba->host->host_lock, flags);
        while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
                m = readl(pHba->reply_port);
                if(m == EMPTY_QUEUE){
@@ -2011,8 +2006,7 @@ static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
                        if(m == EMPTY_QUEUE){ 
                                // This really should not happen
                                printk(KERN_ERR"dpti: Could not get reply frame\n");
-                               spin_unlock_irqrestore(&io_request_lock,flags);
-                               return;
+                               goto out;
                        }
                }
                reply = (ulong)bus_to_virt(m);
@@ -2067,9 +2061,7 @@ static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
                wmb();
                rmb();
        }
-       spin_unlock_irqrestore(&io_request_lock, flags);
-       return;
-
+out:   spin_unlock_irqrestore(&pHba->host->host_lock, flags);
 }
 
 static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d)
@@ -2342,18 +2334,14 @@ static s32 adpt_rescan(adpt_hba* pHba)
        s32 rcode;
        ulong flags;
 
-       spin_lock_irqsave(&io_request_lock, flags);
-       if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
-               spin_unlock_irqrestore(&io_request_lock, flags);
-               return rcode;
-       }
-
-       if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
-               spin_unlock_irqrestore(&io_request_lock, flags);
-               return rcode;
-       }
-       spin_unlock_irqrestore(&io_request_lock, flags);
-       return 0;
+       spin_lock_irqsave(&pHba->host->host_lock, flags);
+       if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
+               goto out;
+       if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
+               goto out;
+       rcode = 0;
+out:   spin_unlock_irqrestore(&pHba->host->host_lock, flags);
+       return rcode;
 }
 
 
index fa97dfb7bdde0633798d6af71dcb021f8352552b..519419267185ca6daaa90627acc144d64e9ff4e4 100644 (file)
@@ -1,6 +1,13 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      01 Jan 2002 Rev. 7.20 for linux 2.5.1
+ *        + Use the dynamic DMA mapping API.
+ *
+ *      19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ *        + Use SCpnt->sc_data_direction if set.
+ *        + Use sglist.page instead of sglist.address.
+ *
  *      11 Dec 2001 Rev. 7.00 for linux 2.5.1
  *        + Use host->host_lock instead of io_request_lock.
  *
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *  Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
+ *  Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com)
  *
  *  Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
  *
@@ -634,7 +641,7 @@ struct mscp {
    u_int32_t data_len;   /* If sg=0 Data Length, if sg=1 sglist length */
    u_int32_t cpp_index;  /* Index of address to be returned in sp */
    u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */
-   u_int32_t sp_addr;    /* Address where sp is DMA'ed when cp completes */
+   u_int32_t sp_dma_addr;  /* Address where sp is DMA'ed when cp completes */
    u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */
    /* Additional fields begin here. */
    Scsi_Cmnd *SCpnt;
@@ -656,7 +663,11 @@ struct hostdata {
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or EISA/PCI */
    unsigned char protocol_rev;          /* EATA 2.0 rev., 'A' or 'B' or 'C' */
-   struct mssp sp[2];                   /* Returned status for this board */
+   unsigned char is_pci;                /* TRUE is bus type is PCI */
+   struct pci_dev *pdev;                /* pdev for PCI bus, NULL otherwise */
+   struct mssp *sp_cpu_addr;            /* cpu addr for DMA buffer sp */
+   dma_addr_t sp_dma_addr;              /* dma handle for DMA buffer sp */
+   struct mssp sp;                      /* Local copy of sp buffer */
    };
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
@@ -693,10 +704,11 @@ static unsigned long io_port[] = {
 #define HD(board) ((struct hostdata *) &sh[board]->hostdata)
 #define BN(board) (HD(board)->board_name)
 
-#define H2DEV(x) htonl(x)
-#define DEV2H(x) H2DEV(x)
+/* Device is Big Endian */
+#define H2DEV(x) cpu_to_be32(x)
+#define DEV2H(x) be32_to_cpu(x)
+
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
 static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
@@ -855,7 +867,7 @@ static inline struct pci_dev *get_pci_dev(unsigned long port_base) {
 
 static inline int port_detect \
       (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {
-   unsigned char irq, dma_channel, subversion, i;
+   unsigned char irq, dma_channel, subversion, i, is_pci = FALSE;
    unsigned char protocol_rev;
    struct eata_info info;
    char *bus_type, dma_name[16], tag_type;
@@ -907,10 +919,12 @@ static inline int port_detect \
 
    if (!setup_done && j > 0 && j <= MAX_PCI) {
       bus_type = "PCI";
+      is_pci = TRUE;
       subversion = ESA;
       }
    else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) {
       bus_type = "PCI";
+      is_pci = TRUE;
       subversion = ESA;
       }
    else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) {
@@ -923,6 +937,7 @@ static inline int port_detect \
       }
    else if (port_base > MAX_ISA_ADDR) {
       bus_type = "PCI";
+      is_pci = TRUE;
       subversion = ESA;
       }
    else {
@@ -963,7 +978,13 @@ static inline int port_detect \
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
              name, irq);
 
-   pdev = get_pci_dev(port_base);
+   if (is_pci) {
+      pdev = get_pci_dev(port_base);
+      if (!pdev) 
+         printk("%s: warning, failed to get pci_dev structure.\n", name);
+      }
+   else
+      pdev = NULL;
 
    if (pdev && (irq != pdev->irq)) {
       printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, pdev->irq);
@@ -993,7 +1014,7 @@ static inline int port_detect \
 
    /* Set board configuration */
    memset((char *)&config, 0, sizeof(struct eata_config));
-   config.len = (ushort) htons((ushort)510);
+   config.len = (ushort) cpu_to_be16((ushort)510);
    config.ocena = TRUE;
 
    if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) {
@@ -1022,14 +1043,16 @@ static inline int port_detect \
    sh[j]->n_io_port = REGION_SIZE;
    sh[j]->dma_channel = dma_channel;
    sh[j]->irq = irq;
-   sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size);
+   sh[j]->sg_tablesize = (ushort) be16_to_cpu(info.scatt_size);
    sh[j]->this_id = (ushort) info.host_addr[3];
-   sh[j]->can_queue = (ushort) ntohs(info.queue_size);
+   sh[j]->can_queue = (ushort) be16_to_cpu(info.queue_size);
    sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
    sh[j]->select_queue_depths = select_queue_depths;
    memset(HD(j), 0, sizeof(struct hostdata));
    HD(j)->subversion = subversion;
    HD(j)->protocol_rev = protocol_rev;
+   HD(j)->is_pci = is_pci;
+   HD(j)->pdev = pdev;
    HD(j)->board_number = j;
 
    if (HD(j)->subversion == ESA)
@@ -1038,14 +1061,14 @@ static inline int port_detect \
       unsigned long flags;
       scsi_register_blocked_host(sh[j]);
       sh[j]->unchecked_isa_dma = TRUE;
-      
+
       flags=claim_dma_lock();
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
       release_dma_lock(flags);
-      
+
       }
 
    strcpy(BN(j), name);
@@ -1094,6 +1117,13 @@ static inline int port_detect \
          return FALSE;
          }
 
+   if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, 
+         sizeof(struct mssp), &HD(j)->sp_dma_addr))) {
+      printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j));
+      eata2x_release(sh[j]);
+      return FALSE;
+      }
+
    if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
        max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
 
@@ -1108,7 +1138,7 @@ static inline int port_detect \
    else                                 tag_type = 'n';
 
    if (j == 0) {
-      printk("EATA/DMA 2.0x: Copyright (C) 1994-2001 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994-2002 Dario Ballabio.\n");
       printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c.\n",
              driver_name, tag_type, YESNO(linked_comm), max_queue_depth,
              YESNO(rev_scan), YESNO(ext_tran));
@@ -1144,7 +1174,11 @@ static inline int port_detect \
              info.pci, info.eisa, info.raidnum);
 #endif
 
-   if (pdev) pci_set_master(pdev);
+   if (HD(j)->pdev) {
+      pci_set_master(HD(j)->pdev);
+      if (pci_set_dma_mask(HD(j)->pdev, 0xffffffff))
+         printk("%s: warning, pci_set_dma_mask failed.\n", BN(j));
+      }
 
    return TRUE;
 }
@@ -1271,25 +1305,92 @@ int eata2x_detect(Scsi_Host_Template *tpnt) {
    return j;
 }
 
-static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
-   unsigned int k;
+static inline void map_dma(unsigned int i, unsigned int j) {
+   unsigned int k, count, pci_dir;
    struct scatterlist *sgpnt;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (SCpnt->sense_buffer)
+      cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer,
+                           sizeof SCpnt->sense_buffer, PCI_DMA_FROMDEVICE));
+
+   cpp->sense_len = sizeof SCpnt->sense_buffer;
+
+   if (!SCpnt->use_sg) {
+
+      if (!SCpnt->request_bufflen)
+         cpp->data_address = V2DEV(SCpnt->request_buffer);
+
+      else if (SCpnt->request_buffer)
+         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
+                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+
+      cpp->data_len = H2DEV(SCpnt->request_bufflen);
+      return;
+      }
 
    sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
 
-   for (k = 0; k < SCpnt->use_sg; k++) {
-      cpp->sglist[k].address = V2DEV(sgpnt[k].address);
-      cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
+   for (k = 0; k < count; k++) {
+      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
+      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
       }
 
+   cpp->sg = TRUE;
    cpp->data_address = V2DEV(cpp->sglist);
    cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
 }
 
-static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
-   unsigned int i, j, k;
+static void unmap_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
    struct mscp *cpp;
-   struct mssp *spp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                       DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                       DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static void sync_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                          DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, 
+                         SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                          DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
+   unsigned int k;
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
@@ -1300,9 +1401,53 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    static const unsigned char data_none_cmds[] = {
       0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,
       0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,
-      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5
+      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00
       };
 
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i];
+   SCpnt = cpp->SCpnt;
+
+   if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
+      cpp->din  = TRUE;
+      cpp->dout = FALSE;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
+      cpp->din  = FALSE;
+      cpp->dout = TRUE;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {
+      cpp->din  = FALSE;
+      cpp->dout = FALSE;
+      return;
+      }
+
+   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) 
+      panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
+
+   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+         cpp->dout = TRUE;
+         break;
+         }
+
+   if ((cpp->din = !cpp->dout))
+      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
+         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
+            cpp->din = FALSE;
+            break;
+            }
+
+}
+
+static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+   unsigned int i, j, k;
+   struct mscp *cpp;
+
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->host->hostdata)->board_number;
 
@@ -1334,11 +1479,8 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
 
-   /* Set pointer to status packet structure */
-   spp = &HD(j)->sp[0];
-
-   /* The EATA protocol uses Big Endian format */
-   cpp->sp_addr = V2DEV(spp);
+   /* Set pointer to status packet structure, Big Endian format */
+   cpp->sp_dma_addr = H2DEV(HD(j)->sp_dma_addr);
 
    SCpnt->scsi_done = done;
    cpp->cpp_index = i;
@@ -1348,19 +1490,6 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
                         BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
-   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
-     if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-        cpp->dout = TRUE;
-        break;
-        }
-
-   if ((cpp->din = !cpp->dout))
-      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
-        if (SCpnt->cmnd[0] == data_none_cmds[k]) {
-           cpp->din = FALSE;
-           break;
-           }
-
    cpp->reqsen = TRUE;
    cpp->dispri = TRUE;
 #if 0
@@ -1371,8 +1500,13 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
-   cpp->sense_len = sizeof SCpnt->sense_buffer;
+   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+   /* Use data transfer direction SCpnt->sc_data_direction */
+   scsi_to_dev_dir(i, j);
+
+   /* Map DMA buffers and SG list */
+   map_dma(i, j);
 
    if (SCpnt->device->tagged_queue) {
 
@@ -1392,17 +1526,6 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
       cpp->mess[1] = SCpnt->device->current_tag++;
       }
 
-   if (SCpnt->use_sg) {
-      cpp->sg = TRUE;
-      build_sg_list(cpp, SCpnt);
-      }
-   else {
-      cpp->data_address = V2DEV(SCpnt->request_buffer);
-      cpp->data_len = H2DEV(SCpnt->request_bufflen);
-      }
-
-   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
-
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type)) {
       HD(j)->cp_stat[i] = READY;
@@ -1412,6 +1535,7 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    /* Send control packet to the board */
    if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
+      unmap_dma(i, j);
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
@@ -1468,6 +1592,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
 
       if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
+         unmap_dma(i, j);
          SCarg->host_scribble = NULL;
          HD(j)->cp_stat[i] = FREE;
          printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
@@ -1489,6 +1614,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
       }
 
    if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+      unmap_dma(i, j);
       SCarg->result = DID_ABORT << 16;
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
@@ -1597,6 +1723,7 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
 
       if (HD(j)->cp_stat[i] == IN_RESET) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1609,6 +1736,7 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1821,7 +1949,7 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
 static inline void ihdlr(int irq, unsigned int j) {
    Scsi_Cmnd *SCpnt;
    unsigned int i, k, c, status, tstatus, reg;
-   struct mssp *dspp, *spp;
+   struct mssp *spp;
    struct mscp *cpp;
 
    if (sh[j]->irq != irq)
@@ -1843,14 +1971,13 @@ static inline void ihdlr(int irq, unsigned int j) {
       return;
       }
 
-   dspp = &HD(j)->sp[0];
-   spp  = &HD(j)->sp[1];
+   spp  = &HD(j)->sp;
 
    /* Make a local copy just before clearing the interrupt indication */
-   memcpy(spp, dspp, sizeof(struct mssp));
+   memcpy(spp, HD(j)->sp_cpu_addr, sizeof(struct mssp));
 
    /* Clear the completion flag and cp pointer on the dynamic copy of sp */
-   memset(dspp, 0, sizeof(struct mssp));
+   memset(HD(j)->sp_cpu_addr, 0, sizeof(struct mssp));
 
    /* Read the status register to clear the interrupt indication */
    reg = inb(sh[j]->io_port + REG_STATUS);
@@ -1908,6 +2035,8 @@ static inline void ihdlr(int irq, unsigned int j) {
       panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
             BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
+   sync_dma(i, j);
+
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type))
       flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
@@ -1985,6 +2114,7 @@ static inline void ihdlr(int irq, unsigned int j) {
 #else
             status = DID_BUS_BUSY << 16;
 #endif
+
             HD(j)->retries++;
             HD(j)->last_retried_pid = SCpnt->pid;
             }
@@ -2021,6 +2151,8 @@ static inline void ihdlr(int irq, unsigned int j) {
              SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
              reg, HD(j)->iocount);
 
+   unmap_dma(i, j);
+
    /* Set the command state to inactive */
    SCpnt->host_scribble = NULL;
 
@@ -2052,13 +2184,15 @@ int eata2x_release(struct Scsi_Host *shpnt) {
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   if( sh[j]->unchecked_isa_dma ) {
-          scsi_deregister_blocked_host(sh[j]);
-   }
+   if(sh[j]->unchecked_isa_dma) scsi_deregister_blocked_host(sh[j]);
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
+   if (HD(j)->sp_cpu_addr) 
+      pci_free_consistent(HD(j)->pdev, sizeof(struct mssp),
+                          HD(j)->sp_cpu_addr, HD(j)->sp_dma_addr);
+                       
    free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
index de0bad6efaab8948ae7d7c544c8d042dff618575..45d5cdaba88ed1e2c020887e1fb73ca15bc9a530 100644 (file)
@@ -13,7 +13,7 @@ int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *);
 int eata2x_biosparam(Disk *, kdev_t, int *);
 
-#define EATA_VERSION "7.00.00"
+#define EATA_VERSION "7.20.00"
 
 #define EATA {                                                               \
                 name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
index bdd0ac884ad79893db55348287ac38cbce93fdc9..61e3a19a6c108ad653332425e66cd926caed255a 100644 (file)
@@ -382,22 +382,23 @@ enum out_port_type {
    Write_FIFO       = 12
 };
 
-static int               port_base         = 0;
-static unsigned long     bios_base         = 0;
-static int               bios_major        = 0;
-static int               bios_minor        = 0;
-static int               PCI_bus           = 0;
-static int               Quantum           = 0;        /* Quantum board variant */
-static int               interrupt_level   = 0;
-static volatile int      in_command        = 0;
-static Scsi_Cmnd         *current_SC       = NULL;
+/* .bss will zero all the static variables below */
+static int               port_base;
+static unsigned long     bios_base;
+static int               bios_major;
+static int               bios_minor;
+static int               PCI_bus;
+static int               Quantum;      /* Quantum board variant */
+static int               interrupt_level;
+static volatile int      in_command;
+static Scsi_Cmnd         *current_SC;
 static enum chip_type    chip              = unknown;
-static int               adapter_mask      = 0;
-static int               this_id           = 0;
-static int               setup_called      = 0;
+static int               adapter_mask;
+static int               this_id;
+static int               setup_called;
 
 #if DEBUG_RACE
-static volatile int      in_interrupt_flag = 0;
+static volatile int      in_interrupt_flag;
 #endif
 
 static int               SCSI_Mode_Cntl_port;
@@ -1265,9 +1266,9 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
 #if EVERY_ACCESS
         printk( " AFAIL " );
 #endif
-         spin_lock_irqsave(&io_request_lock, flags);
+         spin_lock_irqsave(&current_SC->host->host_lock, flags);
         my_done( DID_BUS_BUSY << 16 );
-         spin_unlock_irqrestore(&io_request_lock, flags);
+         spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
         return;
       }
       current_SC->SCp.phase = in_selection;
@@ -1291,9 +1292,9 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
 #if EVERY_ACCESS
            printk( " SFAIL " );
 #endif
-            spin_lock_irqsave(&io_request_lock, flags);
+            spin_lock_irqsave(&current_SC->host->host_lock, flags);
            my_done( DID_NO_CONNECT << 16 );
-            spin_unlock_irqrestore(&io_request_lock, flags);
+            spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
            return;
         } else {
 #if EVERY_ACCESS
@@ -1638,10 +1639,10 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
 #if EVERY_ACCESS
       printk( "BEFORE MY_DONE. . ." );
 #endif
-      spin_lock_irqsave(&io_request_lock, flags);
+      spin_lock_irqsave(&current_SC->host->host_lock, flags);
       my_done( (current_SC->SCp.Status & 0xff)
               | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
-      spin_unlock_irqrestore(&io_request_lock, flags);
+      spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
 #if EVERY_ACCESS
       printk( "RETURNING.\n" );
 #endif
@@ -1932,11 +1933,11 @@ int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
       0x0a bytes long.  Heads are one less than we need to report.
     */
 
-   if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
+   if (major(dev) != SCSI_DISK0_MAJOR) {
       printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
       return 0;
    }
-   drive = MINOR(dev) >> 4;
+   drive = minor(dev) >> 4;
 
    if (bios_major == 2) {
       switch (Quantum) {
index 9d2b391c0292bc75e3c07d9f4e5b5e572f66c30a..3bb3bef50f06b572b00927afa75870e2f9e79cd5 100644 (file)
@@ -747,7 +747,7 @@ static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd)
 {
        idescsi_scsi_t *scsi = drive->driver_data;
 
-       if (MAJOR(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
+       if (major(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
                return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
        return test_bit(IDESCSI_TRANSFORM, &scsi->transform);
 }
index 5b7a6782529f27cdbe567070d7ebc2df94149fac..5659858c18d95f9a6fd8a7b6467c0d7a4c3caffb 100644 (file)
@@ -855,7 +855,7 @@ unsigned long flags;
 
 /* Get the spin_lock and disable further ints, for SMP */
 
-   CLISPIN_LOCK(flags);
+   CLISPIN_LOCK(instance, flags);
 
 #ifdef PROC_STATISTICS
    hostdata->int_cnt++;
@@ -993,7 +993,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
       write1_io(0, IO_LED_OFF);
 
 /* release the SMP spin_lock and restore irq state */
-      CLISPIN_UNLOCK(flags);
+      CLISPIN_UNLOCK(instance, flags);
       return;
       }
 
@@ -1011,7 +1011,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
       write1_io(0, IO_LED_OFF);
 
 /* release the SMP spin_lock and restore irq state */
-      CLISPIN_UNLOCK(flags);
+      CLISPIN_UNLOCK(instance, flags);
       return;
       }
 
@@ -1433,7 +1433,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
             hostdata->state = S_UNCONNECTED;
 
 /* release the SMP spin_lock and restore irq state */
-            CLISPIN_UNLOCK(flags);
+            CLISPIN_UNLOCK(instance, flags);
             return;
             }
 DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
@@ -1609,7 +1609,7 @@ DB(DB_INTR,printk("-%ld",cmd->pid))
 DB(DB_INTR,printk("} "))
 
 /* release the SMP spin_lock and restore irq state */
-   CLISPIN_UNLOCK(flags);
+   CLISPIN_UNLOCK(instance, flags);
 
 }
 
index 7fe39c451332aafb2a7aa127dd7c06fbb6212ff2..ac72f6a298065988740af68424b666ba1a1f0d26 100644 (file)
@@ -393,8 +393,9 @@ struct IN2000_hostdata {
 # define in2000__INITFUNC(function) __initfunc(function)
 # define in2000__INIT __init
 # define in2000__INITDATA __initdata
-# define CLISPIN_LOCK(flags)   spin_lock_irqsave(&io_request_lock, flags)
-# define CLISPIN_UNLOCK(flags) spin_unlock_irqrestore(&io_request_lock, flags)
+# define CLISPIN_LOCK(host,flags)   spin_lock_irqsave(&host->host_lock, flags)
+# define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(&host->host_lock, \
+                                                          flags)
 
 int in2000_detect(Scsi_Host_Template *) in2000__INIT;
 int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
index 04ffa14e6dd36c356b70a5660af46b5098f1079c..a929633a2a07c7556cb685bbf4bddc159fa85f52 100644 (file)
@@ -1769,14 +1769,13 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
       char      *kern_area;
       u_int32_t  datasize;
 
-      /* free io_request_lock */
-      spin_unlock_irq(&io_request_lock);
+      spin_unlock_irq(&SC->host->host_lock);
 
       /* wait for the command to finish */
       down(&ha->ioctl_sem);
 
       /* reobtain the lock */
-      spin_lock_irq(&io_request_lock);
+      spin_lock_irq(&SC->host->host_lock);
 
       /* command finished -- copy back */
       user_area = *((char **) &SC->cmnd[4]);
@@ -1911,31 +1910,30 @@ ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) {
 /****************************************************************************/
 void
 do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
-   ips_ha_t         *ha;
+   ips_ha_t         *ha = (ips_ha_t *) dev_id;
    unsigned long     cpu_flags;
+   struct Scsi_Host *host = ips_sh[ha->host_num];
 
    METHOD_TRACE("do_ipsintr", 2);
 
-   ha = (ips_ha_t *) dev_id;
-
-   spin_lock_irqsave(&io_request_lock, cpu_flags);
+   spin_lock_irqsave(&host->host_lock, cpu_flags);
 
    if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
-      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+      spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
       return ;
    }
 
    if (!ha) {
       clear_bit(IPS_IN_INTR, &ha->flags);
-      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+      spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
       return;
    }
 
    if (!ha->active) {
       clear_bit(IPS_IN_INTR, &ha->flags);
-      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+      spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
       return;
    }
@@ -1944,10 +1942,11 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
 
    clear_bit(IPS_IN_INTR, &ha->flags);
 
-   spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+   spin_unlock_irqrestore(&host->host_lock, cpu_flags);
 
    /* start the next command */
    ips_next(ha, IPS_INTR_ON);
+   return;
 }
 
 /****************************************************************************/
@@ -2487,8 +2486,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
             task.routine = ips_scheduled_flash_bios;
             task.data = (void *) &flash_data;
 
-            /* Unlock the master lock */
-            spin_unlock_irq(&io_request_lock);
+            /* Unlock the per-board lock */
+            spin_unlock_irq(&SC->host->host_lock);
 
             queue_task(&task, &tq_immediate);
             mark_bh(IMMEDIATE_BH);
@@ -2496,8 +2495,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
             /* Wait for the flash to complete */
             down(&ha->flash_ioctl_sem);
 
-            /* Obtain the master lock */
-            spin_lock_irq(&io_request_lock);
+            /* Obtain the per-board lock */
+            spin_lock_irq(&SC->host->host_lock);
 
             return (flash_data.retcode);
          }
@@ -2604,8 +2603,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
             task.routine = ips_flash_bios_section;
             task.data = (void *) &flash_data;
 
-            /* Unlock the master lock */
-            spin_unlock_irq(&io_request_lock);
+            /* Unlock the per-board lock */
+            spin_unlock_irq(&SC->host->host_lock);
 
             queue_task(&task, &tq_immediate);
             mark_bh(IMMEDIATE_BH);
@@ -2613,8 +2612,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
             /* Wait for the flash to complete */
             down(&ha->flash_ioctl_sem);
 
-            /* Obtain the master lock */
-            spin_lock_irq(&io_request_lock);
+            /* Obtain the per-board lock */
+            spin_lock_irq(&SC->host->host_lock);
 
             return (flash_data.retcode);
          }
@@ -3572,18 +3571,21 @@ ips_next(ips_ha_t *ha, int intr) {
    int                   intr_status;
    unsigned long         cpu_flags;
    unsigned long         cpu_flags2;
+   struct Scsi_Host *host;
 
    METHOD_TRACE("ips_next", 1);
 
    if (!ha)
       return ;
 
+   host = ips_sh[ha->host_num];
+
    /*
     * Block access to the queue function so
     * this command won't time out
     */
    if (intr == IPS_INTR_ON) {
-       spin_lock_irqsave(&io_request_lock, cpu_flags2);
+       spin_lock_irqsave(&host->host_lock, cpu_flags2);
        intr_status = IPS_INTR_IORL;
    } else {
        intr_status = intr;
@@ -3608,7 +3610,7 @@ ips_next(ips_ha_t *ha, int intr) {
    }
 
    if (intr == IPS_INTR_ON)
-       spin_unlock_irqrestore(&io_request_lock, cpu_flags2);
+       spin_unlock_irqrestore(&host->host_lock, cpu_flags2);
 
 #ifndef NO_IPS_CMDLINE
    /*
@@ -6604,6 +6606,8 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
 
          clear_bit(IPS_IN_INTR, &ha->flags);
       } else if (intr == IPS_INTR_HAL) {
+        struct Scsi_Host *host = ips_sh[ha->host_num];
+
          if (ha->waitflag == FALSE) {
             /*
              * controller generated an interrupt to
@@ -6621,7 +6625,7 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
           * We were called under the HA lock so we can assume that interrupts
           * are masked.
           */
-         spin_lock(&io_request_lock);
+         spin_lock(&host->host_lock);
 
          while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
             udelay(1000);
@@ -6630,7 +6634,7 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
 
          clear_bit(IPS_IN_INTR, &ha->flags);
 
-         spin_unlock(&io_request_lock);
+         spin_unlock(&host->host_lock);
       }
 
       udelay(1000); /* 1 milisecond */
index 88c4b4ee6b0e94e6f396e3376025f7947824eabd..777c6409d980617ce4cf8e8fafe81f40f9317b09 100644 (file)
@@ -275,11 +275,6 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
        int                                     z;
     unsigned long              flags;
 
-    /*
-     * Disable interrupts, if they aren't already disabled and acquire
-     * the I/O spinlock.
-     */
-    spin_lock_irqsave (&io_request_lock, flags);
 
        DEB(printk ("\npci2000 received interrupt "));
        for ( z = 0; z < NumAdapters;  z++ )                                                                            // scan for interrupt to process
@@ -298,9 +293,10 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
        if ( !shost )
                {
                DEB (printk ("\npci2000: not my interrupt"));
-               goto irq_return;
+               goto out;
                }
 
+       spin_lock_irqsave(&shost->host_lock, flags);
        padapter = HOSTDATA(shost);
 
        tag0 = tag & 0x7F;                                                                                                                      // mask off the error bit
@@ -392,14 +388,10 @@ irqProceed:;
        outb_p (CMD_DONE, padapter->cmd);                                                                               // complete the op
        OpDone (SCpnt, DID_OK << 16);
 
-irq_return:;
-    /*
-     * Release the I/O spinlock and restore the original flags
-     * which will enable interrupts if and only if they were
-     * enabled on entry.
-     */
-    spin_unlock_irqrestore (&io_request_lock, flags);
-       }
+irq_return:
+    spin_unlock_irqrestore(&shost->host_flag, flags);
+out:;
+}
 /****************************************************************
  *     Name:   Pci2000_QueueCommand
  *
index 1dddd50046520887d0d6207a7792d7c9c15d0906..f96194aaeaf061732a23abb693f572d616077f3f 100644 (file)
@@ -1152,6 +1152,7 @@ static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
 static void TimerExpiry (unsigned long data)
        {
        PADAPTER2220I   padapter = (PADAPTER2220I)data;
+       struct Scsi_Host *host = padapter->SCpnt->host;
        POUR_DEVICE             pdev = padapter->pdev;
        UCHAR                   status = IDE_STATUS_BUSY;
        UCHAR                   temp, temp1;
@@ -1161,7 +1162,7 @@ static void TimerExpiry (unsigned long data)
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
-    spin_lock_irqsave (&io_request_lock, flags);
+    spin_lock_irqsave (&host->host_lock, flags);
        DEB (printk ("\nPCI2220I: Timeout expired "));
 
        if ( padapter->failinprog )
@@ -1295,7 +1296,7 @@ timerExpiryDone:;
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
-    spin_unlock_irqrestore (&io_request_lock, flags);
+    spin_unlock_irqrestore (&host->host_lock, flags);
        }
 /****************************************************************
  *     Name:                   SetReconstruct  :LOCAL
@@ -1328,7 +1329,8 @@ static LONG SetReconstruct (POUR_DEVICE pdev, int index)
  ****************************************************************/
 static void ReconTimerExpiry (unsigned long data)
        {
-       PADAPTER2220I   padapter;
+       PADAPTER2220I   padapter = (PADAPTER2220I)data;
+       struct Scsi_Host *host = padapter->SCpnt->host;
        POUR_DEVICE             pdev;
        ULONG                   testsize = 0;
        PIDENTIFY_DATA  pid;
@@ -1342,9 +1344,8 @@ static void ReconTimerExpiry (unsigned long data)
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
-    spin_lock_irqsave (&io_request_lock, flags);
+    spin_lock_irqsave(&host->host_lock, flags);
 
-       padapter = (PADAPTER2220I)data;
        if ( padapter->SCpnt )
                goto reconTimerExpiry;
 
@@ -1567,7 +1568,7 @@ reconTimerExpiry:;
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
-    spin_unlock_irqrestore (&io_request_lock, flags);
+    spin_unlock_irqrestore(&host->host_lock, flags);
        }
 /****************************************************************
  *     Name:   Irq_Handler     :LOCAL
@@ -1596,12 +1597,6 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
        ULONG                           zl;
     unsigned long              flags;
 
-    /*
-     * Disable interrupts, if they aren't already disabled and acquire
-     * the I/O spinlock.
-     */
-    spin_lock_irqsave (&io_request_lock, flags);
-
 //     DEB (printk ("\npci2220i received interrupt\n"));
 
        for ( z = 0; z < NumAdapters;  z++ )                                                            // scan for interrupt to process
@@ -1619,9 +1614,10 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
        if ( !shost )
                {
                DEB (printk ("\npci2220i: not my interrupt"));
-               goto irq_return;
+               goto out;
                }
 
+       spin_lock_irqsave(&shost->host_lock, flags);
        padapter = HOSTDATA(shost);
        pdev = padapter->pdev;
        SCpnt = padapter->SCpnt;
@@ -2023,13 +2019,9 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
                zl = DID_OK << 16;
 
        OpDone (padapter, zl);
-irq_return:;
-    /*
-     * Release the I/O spinlock and restore the original flags
-     * which will enable interrupts if and only if they were
-     * enabled on entry.
-     */
-    spin_unlock_irqrestore (&io_request_lock, flags);
+irq_return:
+    spin_unlock_irqrestore(&shost->host_lock, flags);
+out:;
        }
 /****************************************************************
  *     Name:   Pci2220i_QueueCommand
index 589d8f6d45cc90db9b1bf047d2d342819e89f50f..b3257fc4652b43f13dbc968250cd53e18504a805 100644 (file)
@@ -200,14 +200,11 @@ void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
 
        /* Hardware imposed limit. */
        blk_queue_max_hw_segments(q, SHpnt->sg_tablesize);
-
-       /*
-        * When we remove scsi_malloc soonish, this can die too
-        */
-       blk_queue_max_phys_segments(q, PAGE_SIZE / sizeof(struct scatterlist));
-
        blk_queue_max_sectors(q, SHpnt->max_sectors);
 
+       /* scsi_alloc_sgtable max */
+       blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+
        if (!SHpnt->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
 }
index aea6ca3b6bfbdb20f45f77c6286373fa8b1c8add..4e8745f235602e02d3c2f8795ba8d3a8382a3a27 100644 (file)
@@ -83,7 +83,6 @@ static void __scsi_insert_special(request_queue_t *q, struct request *rq,
        rq->q = NULL;
        rq->bio = rq->biotail = NULL;
        rq->nr_phys_segments = 0;
-       rq->elevator_sequence = 0;
 
        /*
         * We have the option of inserting the head or the tail of the queue.
@@ -92,7 +91,7 @@ static void __scsi_insert_special(request_queue_t *q, struct request *rq,
         * device, or a host that is unable to accept a particular command.
         */
        spin_lock_irqsave(q->queue_lock, flags);
-       __elv_add_request(q, rq, !at_head, 0);
+       _elv_add_request(q, rq, !at_head, 0);
        q->request_fn(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
@@ -262,7 +261,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
                 * the bad sector.
                 */
                SCpnt->request.special = (void *) SCpnt;
-               __elv_add_request(q, &SCpnt->request, 0, 0);
+               _elv_add_request(q, &SCpnt->request, 0, 0);
        }
 
        /*
index 9f8401e7b7e60888da4d3c891b30b81119c0b626..b88aeb25ccb89b028eaa49da39bfed3cc5c7892a 100644 (file)
@@ -254,7 +254,7 @@ static Sg_device ** sg_dev_arr = NULL;
 
 static int sg_open(struct inode * inode, struct file * filp)
 {
-    int dev = MINOR(inode->i_rdev);
+    int dev = minor(inode->i_rdev);
     int flags = filp->f_flags;
     Sg_device * sdp;
     Sg_fd * sfp;
@@ -340,7 +340,7 @@ static int sg_release(struct inode * inode, struct file * filp)
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
         return -ENXIO;
     }
-    SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
+    SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", minor(sdp->i_rdev)));
     sg_fasync(-1, filp, 0);   /* remove filp from async notification list */
     if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
         if (! sdp->detached) {
@@ -369,7 +369,7 @@ static ssize_t sg_read(struct file * filp, char * buf,
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n",
-                               MINOR(sdp->i_rdev), (int)count));
+                               minor(sdp->i_rdev), (int)count));
     if (ppos != &filp->f_pos)
         ; /* FIXME: Hmm.  Seek to the right place, or fail?  */
     if ((k = verify_area(VERIFY_WRITE, buf, count)))
@@ -514,7 +514,7 @@ static ssize_t sg_write(struct file * filp, const char * buf,
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",
-                               MINOR(sdp->i_rdev), (int)count));
+                               minor(sdp->i_rdev), (int)count));
     if (sdp->detached)
        return -ENODEV;
     if (! ((filp->f_flags & O_NONBLOCK) ||
@@ -731,7 +731,7 @@ static int sg_ioctl(struct inode * inode, struct file * filp,
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",
-                               MINOR(sdp->i_rdev), (int)cmd_in));
+                               minor(sdp->i_rdev), (int)cmd_in));
     read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
 
     switch(cmd_in)
@@ -1011,7 +1011,7 @@ static unsigned int sg_poll(struct file * filp, poll_table * wait)
     else if (count < SG_MAX_QUEUE)
         res |= POLLOUT | POLLWRNORM;
     SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",
-                        MINOR(sdp->i_rdev), (int)res));
+                        minor(sdp->i_rdev), (int)res));
     return res;
 }
 
@@ -1024,7 +1024,7 @@ static int sg_fasync(int fd, struct file * filp, int mode)
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",
-                               MINOR(sdp->i_rdev), mode));
+                               minor(sdp->i_rdev), mode));
 
     retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
     return (retval < 0) ? retval : 0;
@@ -1035,7 +1035,7 @@ static int sg_fasync(int fd, struct file * filp, int mode)
 static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
 {
     Scsi_Request * SRpnt = SCpnt->sc_request;
-    int dev = MINOR(SRpnt->sr_request.rq_dev);
+    int dev = minor(SRpnt->sr_request.rq_dev);
     Sg_device * sdp = NULL;
     Sg_fd * sfp;
     Sg_request * srp = NULL;
@@ -1278,7 +1278,7 @@ static int sg_attach(Scsi_Device * scsidp)
     sdp->sgdebug = 0;
     sdp->detached = 0;
     sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
-    sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
+    sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k);
     sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
                              SCSI_GENERIC_MAJOR, k,
                              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
@@ -2415,7 +2415,7 @@ static void sg_clr_srpnt(Scsi_Request * SRpnt)
     SRpnt->sr_bufflen = 0;
     SRpnt->sr_buffer = NULL;
     SRpnt->sr_underflow = 0;
-    SRpnt->sr_request.rq_dev = MKDEV(0, 0);  /* "sg" _disowns_ command blk */
+    SRpnt->sr_request.rq_dev = mk_kdev(0, 0);  /* "sg" _disowns_ command blk */
 }
 
 static int sg_ms_to_jif(unsigned int msecs)
@@ -2694,7 +2694,7 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
                PRINT_PROC("device %d detached ??\n", j);
                continue;
            }
-           dev = MINOR(sdp->i_rdev);
+           dev = minor(sdp->i_rdev);
 
            if (sg_get_nth_sfp(sdp, 0)) {
                PRINT_PROC(" >>> device=sg%d ", dev);
index 085e97d6c14068f4dca93902c0993550689251c4..b4eeaeb2e816f0e4cf30cbe78c2a21e66de10f6e 100644 (file)
@@ -904,11 +904,12 @@ handle_script_int(struct Scsi_Host * host, Scsi_Cmnd * cmd)
 static void
 do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
+    struct Scsi_Host *host = dev_id;
     unsigned long flags;
 
-    spin_lock_irqsave(&io_request_lock, flags);
-    sim710_intr_handle(irq, dev_id, regs);
-    spin_unlock_irqrestore(&io_request_lock, flags);
+    spin_lock_irqsave(&host->host_lock, flags);
+    sim710_intr_handle(irq, host, regs);
+    spin_unlock_irqrestore(&host->host_lock, flags);
 }
 
 
index 83f8b836c4853c56bf8f4c00cc4f1f2b0c8e635f..660cf3bc6bacd60863400441cee886d19af0fcce 100644 (file)
@@ -99,11 +99,11 @@ static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *)
 
 static void sr_release(struct cdrom_device_info *cdi)
 {
-       if (scsi_CDs[MINOR(cdi->dev)].device->sector_size > 2048)
-               sr_set_blocklength(MINOR(cdi->dev), 2048);
-       scsi_CDs[MINOR(cdi->dev)].device->access_count--;
-       if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
-               __MOD_DEC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
+       if (scsi_CDs[minor(cdi->dev)].device->sector_size > 2048)
+               sr_set_blocklength(minor(cdi->dev), 2048);
+       scsi_CDs[minor(cdi->dev)].device->access_count--;
+       if (scsi_CDs[minor(cdi->dev)].device->host->hostt->module)
+               __MOD_DEC_USE_COUNT(scsi_CDs[minor(cdi->dev)].device->host->hostt->module);
        if (sr_template.module)
                __MOD_DEC_USE_COUNT(sr_template.module);
 }
@@ -150,7 +150,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
                /* no changer support */
                return -EINVAL;
        }
-       retval = scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+       retval = scsi_ioctl(scsi_CDs[minor(cdi->dev)].device,
                            SCSI_IOCTL_TEST_UNIT_READY, 0);
 
        if (retval) {
@@ -159,13 +159,13 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
                 * and we will figure it out later once the drive is
                 * available again.  */
 
-               scsi_CDs[MINOR(cdi->dev)].device->changed = 1;
+               scsi_CDs[minor(cdi->dev)].device->changed = 1;
                return 1;       /* This will force a flush, if called from
                                 * check_disk_change */
        };
 
-       retval = scsi_CDs[MINOR(cdi->dev)].device->changed;
-       scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
+       retval = scsi_CDs[minor(cdi->dev)].device->changed;
+       scsi_CDs[minor(cdi->dev)].device->changed = 0;
        /* If the disk changed, the capacity will now be different,
         * so we force a re-read of this information */
        if (retval) {
@@ -179,9 +179,9 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
                 * be trying to use something that is too small if the disc
                 * has changed.
                 */
-               scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
+               scsi_CDs[minor(cdi->dev)].needs_sector_size = 1;
 
-               scsi_CDs[MINOR(cdi->dev)].device->sector_size = 2048;
+               scsi_CDs[minor(cdi->dev)].device->sector_size = 2048;
        }
        return retval;
 }
@@ -253,17 +253,17 @@ static request_queue_t *sr_find_queue(kdev_t dev)
        /*
         * No such device
         */
-       if (MINOR(dev) >= sr_template.dev_max || !scsi_CDs[MINOR(dev)].device)
+       if (minor(dev) >= sr_template.dev_max || !scsi_CDs[minor(dev)].device)
                return NULL;
 
-       return &scsi_CDs[MINOR(dev)].device->request_queue;
+       return &scsi_CDs[minor(dev)].device->request_queue;
 }
 
 static int sr_init_command(Scsi_Cmnd * SCpnt)
 {
        int dev, devm, block=0, this_count, s_size;
 
-       devm = MINOR(SCpnt->request.rq_dev);
+       devm = minor(SCpnt->request.rq_dev);
        dev = DEVICE_NR(SCpnt->request.rq_dev);
 
        SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
@@ -399,20 +399,20 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
 {
        check_disk_change(cdi->dev);
 
-       if (MINOR(cdi->dev) >= sr_template.dev_max
-           || !scsi_CDs[MINOR(cdi->dev)].device) {
+       if (minor(cdi->dev) >= sr_template.dev_max
+           || !scsi_CDs[minor(cdi->dev)].device) {
                return -ENXIO;  /* No such device */
        }
        /*
         * If the device is in error recovery, wait until it is done.
         * If the device is offline, then disallow any access to it.
         */
-       if (!scsi_block_when_processing_errors(scsi_CDs[MINOR(cdi->dev)].device)) {
+       if (!scsi_block_when_processing_errors(scsi_CDs[minor(cdi->dev)].device)) {
                return -ENXIO;
        }
-       scsi_CDs[MINOR(cdi->dev)].device->access_count++;
-       if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
-               __MOD_INC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
+       scsi_CDs[minor(cdi->dev)].device->access_count++;
+       if (scsi_CDs[minor(cdi->dev)].device->host->hostt->module)
+               __MOD_INC_USE_COUNT(scsi_CDs[minor(cdi->dev)].device->host->hostt->module);
        if (sr_template.module)
                __MOD_INC_USE_COUNT(sr_template.module);
 
@@ -421,8 +421,8 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
         * this is the case, and try again.
         */
 
-       if (scsi_CDs[MINOR(cdi->dev)].needs_sector_size)
-               get_sectorsize(MINOR(cdi->dev));
+       if (scsi_CDs[minor(cdi->dev)].needs_sector_size)
+               get_sectorsize(minor(cdi->dev));
 
        return 0;
 }
@@ -671,13 +671,13 @@ void get_capabilities(int i)
  */
 static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
 {
-       Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
+       Scsi_Device *device = scsi_CDs[minor(cdi->dev)].device;
 
        /* set the LUN */
        if (device->scsi_level <= SCSI_2)
                cgc->cmd[1] |= device->lun << 5;
 
-       cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
+       cgc->stat = sr_do_ioctl(minor(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
 
        return cgc->stat;
 }
@@ -766,7 +766,7 @@ void sr_finish()
 
                scsi_CDs[i].cdi.ops = &sr_dops;
                scsi_CDs[i].cdi.handle = &scsi_CDs[i];
-               scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR, i);
+               scsi_CDs[i].cdi.dev = mk_kdev(MAJOR_NR, i);
                scsi_CDs[i].cdi.mask = 0;
                scsi_CDs[i].cdi.capacity = 1;
                /*
@@ -809,7 +809,7 @@ static void sr_detach(Scsi_Device * SDp)
                         * the device.
                         * We should be kind to our buffer cache, however.
                         */
-                       invalidate_device(MKDEV(MAJOR_NR, i), 0);
+                       invalidate_device(mk_kdev(MAJOR_NR, i), 0);
 
                        /*
                         * Reset things back to a sane state so that one can
index da3ec60fe77d24f49e9ebca12354776713826878..6d76a4f2298219f5a0a5837a50e7f331dcddf49a 100644 (file)
@@ -68,7 +68,7 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
        sr_cmd[6] = trk1_te.cdte_addr.msf.minute;
        sr_cmd[7] = trk1_te.cdte_addr.msf.second;
        sr_cmd[8] = trk1_te.cdte_addr.msf.frame;
-       return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+       return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 }
 
 /* We do our own retries because we want to know what the specific
@@ -206,17 +206,17 @@ int sr_tray_move(struct cdrom_device_info *cdi, int pos)
        u_char sr_cmd[10];
 
        sr_cmd[0] = GPCMD_START_STOP_UNIT;
-       sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
-                   ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+       sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+                   ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
        sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
        sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
 
-       return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+       return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 }
 
 int sr_lock_door(struct cdrom_device_info *cdi, int lock)
 {
-       return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+       return scsi_ioctl(scsi_CDs[minor(cdi->dev)].device,
                      lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
                          0);
 }
@@ -227,7 +227,7 @@ int sr_drive_status(struct cdrom_device_info *cdi, int slot)
                /* we have no changer support */
                return -EINVAL;
        }
-       if (0 == test_unit_ready(MINOR(cdi->dev)))
+       if (0 == test_unit_ready(minor(cdi->dev)))
                return CDS_DISC_OK;
 
        return CDS_TRAY_OPEN;
@@ -256,7 +256,7 @@ int sr_disk_status(struct cdrom_device_info *cdi)
        if (!have_datatracks)
                return CDS_AUDIO;
 
-       if (scsi_CDs[MINOR(cdi->dev)].xa_flag)
+       if (scsi_CDs[minor(cdi->dev)].xa_flag)
                return CDS_XA_2_1;
        else
                return CDS_DATA_1;
@@ -265,9 +265,9 @@ int sr_disk_status(struct cdrom_device_info *cdi)
 int sr_get_last_session(struct cdrom_device_info *cdi,
                        struct cdrom_multisession *ms_info)
 {
-       ms_info->addr.lba = scsi_CDs[MINOR(cdi->dev)].ms_offset;
-       ms_info->xa_flag = scsi_CDs[MINOR(cdi->dev)].xa_flag ||
-           (scsi_CDs[MINOR(cdi->dev)].ms_offset > 0);
+       ms_info->addr.lba = scsi_CDs[minor(cdi->dev)].ms_offset;
+       ms_info->xa_flag = scsi_CDs[minor(cdi->dev)].xa_flag ||
+           (scsi_CDs[minor(cdi->dev)].ms_offset > 0);
 
        return 0;
 }
@@ -279,8 +279,8 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
        int result;
 
        sr_cmd[0] = GPCMD_READ_SUBCHANNEL;
-       sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
-                   ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+       sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+                   ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
        sr_cmd[2] = 0x40;       /* I do want the subchannel info */
        sr_cmd[3] = 0x02;       /* Give me medium catalog number info */
        sr_cmd[4] = sr_cmd[5] = 0;
@@ -289,7 +289,7 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
        sr_cmd[8] = 24;
        sr_cmd[9] = 0;
 
-       result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
+       result = sr_do_ioctl(minor(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
 
        memcpy(mcn->medium_catalog_number, buffer + 9, 13);
        mcn->medium_catalog_number[13] = 0;
@@ -314,12 +314,12 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 
        memset(sr_cmd, 0, MAX_COMMAND_SIZE);
        sr_cmd[0] = GPCMD_SET_SPEED;    /* SET CD SPEED */
-       sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
-                   ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+       sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+                   ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
        sr_cmd[2] = (speed >> 8) & 0xff;        /* MSB for speed (in kbytes/sec) */
        sr_cmd[3] = speed & 0xff;       /* LSB */
 
-       if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
+       if (sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
                return -EIO;
        return 0;
 }
@@ -333,7 +333,7 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 {
        u_char sr_cmd[10];
-       int result, target = MINOR(cdi->dev);
+       int result, target = minor(cdi->dev);
        unsigned char buffer[32];
 
        memset(sr_cmd, 0, sizeof(sr_cmd));
@@ -541,7 +541,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
 {
        int target;
 
-       target = MINOR(cdi->dev);
+       target = minor(cdi->dev);
 
        switch (cmd) {
        case BLKGETSIZE:
index a1d4a7db41a67a87d8ee0d463645258a928164dd..1a030a49bd57d70497c51f9188a9ef2b0929fde4 100644 (file)
@@ -158,7 +158,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
        unsigned char cmd[MAX_COMMAND_SIZE];    /* the scsi-command */
        int rc, no_multi, minor;
 
-       minor = MINOR(cdi->dev);
+       minor = minor(cdi->dev);
        if (scsi_CDs[minor].cdi.mask & CDC_MULTI_SESSION)
                return 0;
 
index adacf2fd49a07904037b632a7884c702967488ab..2f7f1cab84b9e8ef5136fd7e6a2fcbda461ca5ca 100644 (file)
@@ -1,6 +1,13 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      01 Jan 2002 Rev. 7.20 for linux 2.5.1
+ *        + Use the dynamic DMA mapping API.
+ *
+ *      19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ *        + Use SCpnt->sc_data_direction if set.
+ *        + Use sglist.page instead of sglist.address.
+ *
  *      11 Dec 2001 Rev. 7.00 for linux 2.5.1
  *        + Use host->host_lock instead of io_request_lock.
  *
  *
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
+ *  Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com)
  *
  *  Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
  *
@@ -377,6 +384,7 @@ MODULE_AUTHOR("Dario Ballabio");
 #include "u14-34f.h"
 #include <linux/stat.h>
 #include <linux/config.h>
+#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
@@ -483,13 +491,13 @@ struct mscp {
    unsigned char clink_id;              /* identifies command in chain */
    unsigned char use_sg;                /* (if sg is set) 8 bytes per list */
    unsigned char sense_len;
-   unsigned char scsi_cdbs_len;         /* 6, 10, or 12 */
-   unsigned char scsi_cdbs[12];         /* SCSI commands */
+   unsigned char cdb_len;               /* 6, 10, or 12 */
+   unsigned char cdb[12];               /* SCSI Command Descriptor Block */
    unsigned char adapter_status;        /* non-zero indicates HA error */
    unsigned char target_status;         /* non-zero indicates target error */
    unsigned int sense_addr PACKED;
    Scsi_Cmnd *SCpnt;
-   unsigned int index;                  /* cp index */
+   unsigned int cpp_index;              /* cp index */
    struct sg_list *sglist;
    };
 
@@ -507,6 +515,7 @@ struct hostdata {
    unsigned int retries;                /* Number of internal retries */
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or ESA */
+   struct pci_dev *pdev;                /* Always NULL */
    unsigned char heads;
    unsigned char sectors;
 
@@ -537,21 +546,11 @@ static unsigned long io_port[] = {
 #define HD(board) ((struct hostdata *) &sh[board]->hostdata)
 #define BN(board) (HD(board)->board_name)
 
-#define SWAP_BYTE(x) ((unsigned long)( \
-        (((unsigned long)(x) & 0x000000ffU) << 24) | \
-        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
-        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
-        (((unsigned long)(x) & 0xff000000U) >> 24)))
+/* Device is Little Endian */
+#define H2DEV(x) cpu_to_le32(x)
+#define DEV2H(x) le32_to_cpu(x)
 
-#if defined(__BIG_ENDIAN)
-#define H2DEV(x) SWAP_BYTE(x)
-#else
-#define H2DEV(x) (x)
-#endif
-
-#define DEV2H(x) H2DEV(x)
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
 static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
@@ -653,8 +652,8 @@ static int board_inquiry(unsigned int j) {
    cpp->xdir = DTD_IN;
    cpp->data_address = V2DEV(HD(j)->board_id);
    cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
-   cpp->scsi_cdbs_len = 6;
-   cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;
+   cpp->cdb_len = 6;
+   cpp->cdb[0] = HA_CMD_INQUIRY;
 
    if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
       printk("%s: board_inquiry, adapter busy.\n", BN(j));
@@ -832,14 +831,14 @@ static inline int port_detect \
       unsigned long flags;
       scsi_register_blocked_host(sh[j]);
       sh[j]->unchecked_isa_dma = TRUE;
-      
+
       flags=claim_dma_lock();
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
       release_dma_lock(flags);
-      
+
       sh[j]->dma_channel = dma_channel;
       sprintf(BN(j), "U14F%d", j);
       bus_type = "ISA";
@@ -879,7 +878,7 @@ static inline int port_detect \
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
 
    if (j == 0) {
-      printk("UltraStor 14F/34F: Copyright (C) 1994-2001 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-2002 Dario Ballabio.\n");
       printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n",
              driver_name, YESNO(have_old_firmware), YESNO(linked_comm),
              max_queue_depth, YESNO(ext_tran));
@@ -949,8 +948,7 @@ static int option_setup(char *str) {
    return 1;
 }
 
-int u14_34f_detect(Scsi_Host_Template *tpnt)
-{
+int u14_34f_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k;
 
    tpnt->proc_name = "u14-34f";
@@ -978,26 +976,95 @@ int u14_34f_detect(Scsi_Host_Template *tpnt)
    return j;
 }
 
-static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
-   unsigned int k, data_len = 0;
+static inline void map_dma(unsigned int i, unsigned int j) {
+   unsigned int data_len = 0;
+   unsigned int k, count, pci_dir;
    struct scatterlist *sgpnt;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (SCpnt->sense_buffer)
+      cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer,
+                           sizeof SCpnt->sense_buffer, PCI_DMA_FROMDEVICE));
+
+   cpp->sense_len = sizeof SCpnt->sense_buffer;
+
+   if (!SCpnt->use_sg) {
+
+      if (!SCpnt->request_bufflen)
+         cpp->data_address = V2DEV(SCpnt->request_buffer);
+
+      else if (SCpnt->request_buffer)
+         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
+                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+
+      cpp->data_len = H2DEV(SCpnt->request_bufflen);
+      return;
+      }
 
    sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
 
-   for (k = 0; k < SCpnt->use_sg; k++) {
-      cpp->sglist[k].address = V2DEV(sgpnt[k].address);
-      cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
+   for (k = 0; k < count; k++) {
+      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
+      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
       data_len += sgpnt[k].length;
       }
 
+   cpp->sg = TRUE;
    cpp->use_sg = SCpnt->use_sg;
    cpp->data_address = V2DEV(cpp->sglist);
    cpp->data_len = H2DEV(data_len);
 }
 
-static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
-   unsigned int i, j, k;
+static void unmap_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                       DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                       DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static void sync_dma(unsigned int i, unsigned int j) {
+   unsigned int pci_dir;
    struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+   if (DEV2H(cpp->sense_addr))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+                          DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+   if (SCpnt->use_sg) 
+      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, 
+                         SCpnt->use_sg, pci_dir);
+
+   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), 
+                          DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
+   unsigned int k;
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
@@ -1008,9 +1075,51 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    static const unsigned char data_none_cmds[] = {
       0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,
       0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,
-      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5
+      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00
       };
 
+   struct mscp *cpp;
+   Scsi_Cmnd *SCpnt;
+
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+
+   if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
+      cpp->xdir = DTD_IN;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
+      cpp->xdir = DTD_OUT;
+      return;
+      }
+   else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {
+      cpp->xdir = DTD_NONE;
+      return;
+      }
+
+   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) 
+      panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
+
+   cpp->xdir = DTD_IN;
+
+   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+         cpp->xdir = DTD_OUT;
+         break;
+         }
+
+   if (cpp->xdir == DTD_IN)
+      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
+         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
+            cpp->xdir = DTD_NONE;
+            break;
+            }
+
+}
+
+static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+   unsigned int i, j, k;
+   struct mscp *cpp;
+
    /* j is the board number */
    j = ((struct hostdata *) SCpnt->host->hostdata)->board_number;
 
@@ -1042,47 +1151,26 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
    SCpnt->scsi_done = done;
-   cpp->index = i;
-   SCpnt->host_scribble = (unsigned char *) &cpp->index;
+   cpp->cpp_index = i;
+   SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
                         BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
-   cpp->xdir = DTD_IN;
-
-   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
-      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-         cpp->xdir = DTD_OUT;
-         break;
-         }
-
-   if (cpp->xdir == DTD_IN)
-      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
-         if (SCpnt->cmnd[0] == data_none_cmds[k]) {
-            cpp->xdir = DTD_NONE;
-            break;
-            }
-
    cpp->opcode = OP_SCSI;
    cpp->channel = SCpnt->channel;
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
-   cpp->sense_len = sizeof SCpnt->sense_buffer;
+   cpp->cdb_len = SCpnt->cmd_len;
+   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
-   if (SCpnt->use_sg) {
-      cpp->sg = TRUE;
-      build_sg_list(cpp, SCpnt);
-      }
-   else {
-      cpp->data_address = V2DEV(SCpnt->request_buffer);
-      cpp->data_len = H2DEV(SCpnt->request_bufflen);
-      }
+   /* Use data transfer direction SCpnt->sc_data_direction */
+   scsi_to_dev_dir(i, j);
 
-   cpp->scsi_cdbs_len = SCpnt->cmd_len;
-   memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len);
+   /* Map DMA buffers and SG list */
+   map_dma(i, j);
 
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type)) {
@@ -1092,6 +1180,7 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
       }
 
    if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+      unmap_dma(i, j);
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
@@ -1154,6 +1243,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
 
       if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
+         unmap_dma(i, j);
          SCarg->host_scribble = NULL;
          HD(j)->cp_stat[i] = FREE;
          printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
@@ -1175,6 +1265,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
       }
 
    if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+      unmap_dma(i, j);
       SCarg->result = DID_ABORT << 16;
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
@@ -1272,18 +1363,19 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
 #endif
 
    HD(j)->in_reset = TRUE;
-   
+
    spin_unlock_irq(&sh[j]->host_lock);
    time = jiffies;
    while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
    spin_lock_irq(&sh[j]->host_lock);
-   
+
    printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
 
    for (i = 0; i < sh[j]->can_queue; i++) {
 
       if (HD(j)->cp_stat[i] == IN_RESET) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1296,6 +1388,7 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
          SCpnt = HD(j)->cp[i].SCpnt;
+         unmap_dma(i, j);
          SCpnt->result = DID_RESET << 16;
          SCpnt->host_scribble = NULL;
 
@@ -1536,23 +1629,25 @@ static inline void ihdlr(int irq, unsigned int j) {
       return;
       }
 
-   spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
-   cpp = spp;
+   ret = inl(sh[j]->io_port + REG_ICM);
 
    /* Clear interrupt pending flag */
    outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
-#if defined(DEBUG_GENERATE_ABORTS)
-   if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
-#endif
-
    /* Find the mailbox to be serviced on this board */
-   i = cpp - HD(j)->cp;
+   for (i = 0; i < sh[j]->can_queue; i++)
+      if (V2DEV(&(HD(j)->cp[i])) == ret) break;
 
-   if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
-                                     || i >= sh[j]->can_queue)
+   if (i >= sh[j]->can_queue)
       panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
-            (void *)ret, HD(j)->cp);
+            (void *)ret, (void *)V2DEV(HD(j)->cp));
+
+   cpp = &(HD(j)->cp[i]);
+   spp = cpp;
+
+#if defined(DEBUG_GENERATE_ABORTS)
+   if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
+#endif
 
    if (HD(j)->cp_stat[i] == IGNORE) {
       HD(j)->cp_stat[i] = FREE;
@@ -1588,6 +1683,8 @@ static inline void ihdlr(int irq, unsigned int j) {
       panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
             BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
+   sync_dma(i, j);
+
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type))
       flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
@@ -1705,6 +1802,8 @@ static inline void ihdlr(int irq, unsigned int j) {
              SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
              reg, HD(j)->iocount);
 
+   unmap_dma(i, j);
+
    /* Set the command state to inactive */
    SCpnt->host_scribble = NULL;
 
@@ -1736,9 +1835,7 @@ int u14_34f_release(struct Scsi_Host *shpnt) {
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   if( sh[j]->unchecked_isa_dma ) {
-          scsi_deregister_blocked_host(sh[j]);
-   }
+   if(sh[j]->unchecked_isa_dma) scsi_deregister_blocked_host(sh[j]);
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
index d8d1d400fdd90af33fc453ce838e94bf0f8b3191..a044c2b45ddbf64be52a49990fa82d369a02faab 100644 (file)
@@ -13,7 +13,7 @@ int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "7.00.00"
+#define U14_34F_VERSION "7.20.00"
 
 #define ULTRASTOR_14_34F {                                                   \
                 name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
index 1035eb618e986cc0370ea18f68c40de245325c69..ffc728f1c44ba064f5206d33ebb0a91fa1ba0a0d 100644 (file)
@@ -2569,7 +2569,7 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd,
 
 static int cs4281_open_mixdev(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct cs4281_state *s=NULL;
        struct list_head *entry;
 
@@ -3625,7 +3625,7 @@ static int cs4281_release(struct inode *inode, struct file *file)
 
 static int cs4281_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct cs4281_state *s=NULL;
        struct list_head *entry;
 
@@ -3966,7 +3966,7 @@ static unsigned int cs4281_midi_poll(struct file *file,
 static int cs4281_midi_open(struct inode *inode, struct file *file)
 {
        unsigned long flags, temp1;
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct cs4281_state *s=NULL;
        struct list_head *entry;
        list_for_each(entry, &cs4281_devs)
index e79662a952e26cf4c2472c804bb21ed9704cc65f..f88f197984e5f6c1b83728c55023a536dac677ae 100644 (file)
@@ -1835,7 +1835,7 @@ static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wa
 
 static int cs_midi_open(struct inode *inode, struct file *file)
 {
-        int minor = MINOR(inode->i_rdev);
+        unsigned int minor = minor(inode->i_rdev);
         struct cs_card *card=NULL;
         unsigned long flags;
        struct list_head *entry;
@@ -3198,7 +3198,7 @@ static int cs_open(struct inode *inode, struct file *file)
        struct cs_state *state = NULL;
        struct dmabuf *dmabuf = NULL;
        struct list_head *entry;
-        int minor = MINOR(inode->i_rdev);
+        unsigned int minor = minor(inode->i_rdev);
        int ret=0;
        unsigned int tmp;
 
@@ -4047,7 +4047,7 @@ static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
 static int cs_open_mixdev(struct inode *inode, struct file *file)
 {
        int i=0;
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct cs_card *card=NULL;
        struct list_head *entry;
        unsigned int tmp;
@@ -4094,7 +4094,7 @@ static int cs_open_mixdev(struct inode *inode, struct file *file)
 
 static int cs_release_mixdev(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct cs_card *card=NULL;
        struct list_head *entry;
        int i;
index 3da841bb01ec2b02013eeedb00f49be7bf4fe167..db4be377aa721460a104fe113d500ba1d1779a95 100644 (file)
@@ -1029,7 +1029,7 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
 
 static int es1370_open_mixdev(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct list_head *list;
        struct es1370_state *s;
 
@@ -1729,7 +1729,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 
 static int es1370_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
        struct list_head *list;
@@ -2165,7 +2165,7 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
 
 static int es1370_open_dac(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
        struct list_head *list;
@@ -2408,7 +2408,7 @@ static unsigned int es1370_midi_poll(struct file *file, struct poll_table_struct
 
 static int es1370_midi_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
        struct list_head *list;
index 6db33a2dca4750c0d76d92b3261139e4481b90cc..1d8810569115294e58107d263beabd1b4ef444a1 100644 (file)
@@ -913,7 +913,7 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar
 
 static int solo1_open_mixdev(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct solo1_state *s = NULL;
        struct pci_dev *pci_dev;
 
@@ -1590,7 +1590,7 @@ static int solo1_release(struct inode *inode, struct file *file)
 
 static int solo1_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        struct solo1_state *s = NULL;
        struct pci_dev *pci_dev;
@@ -1879,7 +1879,7 @@ static unsigned int solo1_midi_poll(struct file *file, struct poll_table_struct
 
 static int solo1_midi_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
        struct solo1_state *s = NULL;
@@ -2105,7 +2105,7 @@ static int solo1_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int
 
 static int solo1_dmfm_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        struct solo1_state *s = NULL;
        struct pci_dev *pci_dev;
index 84165efc07f9db3e4a7d65dca74ecb4738ff678c..ee0bb06d8ad9c1e44eba7463350e203dbe6ea14c 100644 (file)
@@ -2345,7 +2345,7 @@ static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data)
 static int i810_open_mixdev(struct inode *inode, struct file *file)
 {
        int i;
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct i810_card *card = devs;
 
        for (card = devs; card != NULL; card = card->next)
index e72cc4a11694e1c2b5c79dd65bfc723069e3b602..44633601cbf499fffed8b04296ddb4ab39071872 100644 (file)
@@ -2126,7 +2126,7 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
 /* --------------------------------------------------------------------- */
 static int ess_open_mixdev(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct ess_card *card = NULL;
        struct pci_dev *pdev;
        struct pci_driver *drvr;
@@ -2967,7 +2967,7 @@ free_buffers(struct ess_state *s)
 static int 
 ess_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct ess_state *s = NULL;
        unsigned char fmtm = ~0, fmts = 0;
        struct pci_dev *pdev;
index b18da793dd63310441ff05642139e0c4b310e770..51106fb775df6fe230de398a946e4961f0ac870f 100644 (file)
@@ -1969,7 +1969,7 @@ free_dmabuf(struct pci_dev *pci_dev, struct dmabuf *db)
 
 static int m3_open(struct inode *inode, struct file *file)
 {
-    int minor = MINOR(inode->i_rdev);
+    unsigned int minor = minor(inode->i_rdev);
     struct m3_card *c;
     struct m3_state *s = NULL;
     int i;
@@ -2137,7 +2137,7 @@ out:
 /* OSS /dev/mixer file operation methods */
 static int m3_open_mixdev(struct inode *inode, struct file *file)
 {
-    int minor = MINOR(inode->i_rdev);
+    unsigned int minor = minor(inode->i_rdev);
     struct m3_card *card = devs;
 
     for (card = devs; card != NULL; card = card->next) {
index 7cdcbc6e6f99645d10785ec6b68d4c0aecc124ff..7d3f1c4f57a856e3ba433b82ab38a895d1e41e9f 100644 (file)
@@ -144,7 +144,7 @@ static int get_mixer_levels(caddr_t arg)
 
 static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-       int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+       int dev = minor(file->f_dentry->d_inode->i_rdev);
        int ret = -EINVAL;
 
        /*
@@ -177,7 +177,7 @@ static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *pp
 
 static ssize_t sound_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-       int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+       int dev = minor(file->f_dentry->d_inode->i_rdev);
        int ret = -EINVAL;
        
        lock_kernel();
@@ -204,7 +204,7 @@ static ssize_t sound_write(struct file *file, const char *buf, size_t count, lof
 
 static int sound_open(struct inode *inode, struct file *file)
 {
-       int dev = MINOR(inode->i_rdev);
+       int dev = minor(inode->i_rdev);
        int retval;
 
        DEB(printk("sound_open(dev=%d)\n", dev));
@@ -255,7 +255,7 @@ static int sound_open(struct inode *inode, struct file *file)
 
 static int sound_release(struct inode *inode, struct file *file)
 {
-       int dev = MINOR(inode->i_rdev);
+       int dev = minor(inode->i_rdev);
 
        lock_kernel();
        DEB(printk("sound_release(dev=%d)\n", dev));
@@ -341,7 +341,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        int err, len = 0, dtype;
-       int dev = MINOR(inode->i_rdev);
+       int dev = minor(inode->i_rdev);
 
        if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) {
                /*
@@ -404,7 +404,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
 static unsigned int sound_poll(struct file *file, poll_table * wait)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       int dev = MINOR(inode->i_rdev);
+       int dev = minor(inode->i_rdev);
 
        DEB(printk("sound_poll(dev=%d)\n", dev));
        switch (dev & 0x0f) {
@@ -428,7 +428,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
        int dev_class;
        unsigned long size;
        struct dma_buffparms *dmap = NULL;
-       int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+       int dev = minor(file->f_dentry->d_inode->i_rdev);
 
        dev_class = dev & 0x0f;
        dev >>= 4;
index c1792a6223a1d0bb8cc89f77b484b20d22aa365f..1be04d52c55a4c9b1106da9e70ba45876d7a5c79 100644 (file)
@@ -18,7 +18,8 @@ comment 'Miscellaneous USB options'
    bool '  Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
 fi
 
-comment 'USB Controllers'
+comment 'USB Host Controller Drivers'
+source drivers/usb/hcd/Config.in
 if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
    dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
 fi
@@ -72,6 +73,8 @@ else
    dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
+   dep_tristate '  USB STV680 (Pencam) Camera support' CONFIG_USB_STV680 $CONFIG_USB $CONFIG_VIDEO_DEV
+   dep_tristate '  USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
    dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
 fi
index 0d70c162683db68b369872c44e70a85547049178..b09211ea122ebbd043cc80d48d4e75fda7920ac2 100644 (file)
@@ -10,19 +10,13 @@ O_TARGET    := usbdrv.o
 
 # Objects that export symbols.
 
-export-objs            := usb.o
+export-objs            := usb.o hcd.o ov511.o pwc-uncompress.o
 
 # Multipart objects.
 
-list-multi             := usbcore.o hid.o
-usbcore-objs           := usb.o usb-debug.o hub.o
+list-multi             := usbcore.o hid.o pwc.o
+usbcore-objs           := usb.o usb-debug.o hub.o hcd.o
 hid-objs               := hid-core.o hid-input.o
-
-ifneq ($(CONFIG_USB_PWC),n)
-       export-objs             += pwc-uncompress.o
-       list-multi              += pwc.o
-endif
-
 pwc-objs               := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
 
 
@@ -65,8 +59,10 @@ obj-$(CONFIG_USB_DC2XX)              += dc2xx.o
 obj-$(CONFIG_USB_MDC800)       += mdc800.o
 obj-$(CONFIG_USB_USS720)       += uss720.o
 obj-$(CONFIG_USB_DABUSB)       += dabusb.o
+obj-$(CONFIG_USB_VICAM)                += vicam.o
 obj-$(CONFIG_USB_OV511)                += ov511.o
 obj-$(CONFIG_USB_SE401)                += se401.o
+obj-$(CONFIG_USB_STV680)       += stv680.o
 obj-$(CONFIG_USB_PEGASUS)      += pegasus.o
 obj-$(CONFIG_USB_CATC)         += catc.o
 obj-$(CONFIG_USB_KAWETH)        += kaweth.o
@@ -79,10 +75,16 @@ obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o
 obj-$(CONFIG_USB_USBNET)       += usbnet.o
 
 # Object files in subdirectories
+mod-subdirs    := serial hcd
 
+subdir-$(CONFIG_USB_EHCI_HCD)  += hcd
 subdir-$(CONFIG_USB_SERIAL)    += serial
 subdir-$(CONFIG_USB_STORAGE)   += storage
 
+ifeq ($(CONFIG_USB_EHCI_HCD),y)
+       obj-y += hcd/ehci-hcd.o
+endif
+
 ifeq ($(CONFIG_USB_SERIAL),y)
        obj-y += serial/usb-serial.o
 endif
index 882c53a7d1a477976def7491c9a11e97dab5f733..9eee6a5f913a1ff2eedbb492e3bdd016700e79a0 100644 (file)
@@ -297,7 +297,7 @@ static void acm_softint(void *private)
 
 static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 {
-       struct acm *acm = acm_table[MINOR(tty->device)];
+       struct acm *acm = acm_table[minor(tty->device)];
 
        if (!acm || !acm->dev) return -EINVAL;
 
index 26a6a40c3d065801ba51b9d7bd4809338b7fc5ed..f5073fb2b59b19c1da29f1d77dfc83d5ac84b5a7 100644 (file)
@@ -1947,7 +1947,7 @@ extern inline int prog_dmabuf_out(struct usb_audiodev *as)
 
 static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct list_head *devs, *mdevs;
        struct usb_mixerdev *ms;
        struct usb_audio_state *s;
@@ -2621,7 +2621,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
 
 static int usb_audio_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        DECLARE_WAITQUEUE(wait, current);
        struct list_head *devs, *adevs;
        struct usb_audiodev *as;
index c4786295edbeb0f169c4f8ad318d9dcbf6fe359d..ba1db6f54be4629c14899f09e2d186dfd162115f 100644 (file)
@@ -360,7 +360,7 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp)
        tty->driver_data = NULL;
 
        /* get the bluetooth object associated with this tty pointer */
-       bluetooth = get_bluetooth_by_minor (MINOR(tty->device));
+       bluetooth = get_bluetooth_by_minor (minor(tty->device));
 
        if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
                return -ENODEV;
index 1b3d864312aa927231ef5b3afba07647af827046..40ba92fedcfa7a73948ba91b2331743ab751b6e2 100644 (file)
@@ -579,7 +579,7 @@ static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t *
 
 static int dabusb_open (struct inode *inode, struct file *file)
 {
-       int devnum = MINOR (inode->i_rdev);
+       int devnum = minor (inode->i_rdev);
        pdabusb_t s;
 
        if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
index 931a274dcc8dfae1059ab8bc94ccd78cdb10ae92..08c7485b537dd0ffdeac731f28b1a227615c1220 100644 (file)
@@ -298,7 +298,7 @@ static int camera_open (struct inode *inode, struct file *file)
        int                     value = 0;
 
        down (&state_table_mutex);
-       subminor = MINOR (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
+       subminor = minor (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
        if (subminor < 0 || subminor >= MAX_CAMERAS
                        || !(camera = minor_data [subminor])) {
                up (&state_table_mutex);
index 1075256bc540aec412f52f5c68987ae8d11e1e1c..6f64bd8b3239b4100c64056c150be124982758aa 100644 (file)
@@ -1,7 +1,7 @@
 #
 # USB Host Controller Drivers
 #
-dep_tristate '  EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-# dep_tristate '  OHCI HCD support (EXPERIMENTAL)' CONFIG_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-# dep_tristate '  UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate '  EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate '  OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate '  UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
 
index b9b3f1daa8930fd63553bbcfa91cfaedafe16590..f194a25734c665c4b0d622bef8e824ae37c06e2c 100644 (file)
@@ -218,7 +218,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
 static int hiddev_open(struct inode * inode, struct file * file) {
        struct hiddev_list *list;
 
-       int i = MINOR(inode->i_rdev) - HIDDEV_MINOR_BASE;
+       int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
 
        if (i >= HIDDEV_MINORS || !hiddev_table[i])
                return -ENODEV;
index 88111927395ef7be447e831008d18b2f6aa69618..3b12890a425d31f3161dca3b973ba0dd9d2917eb 100644 (file)
@@ -201,7 +201,7 @@ static int usblp_check_status(struct usblp *usblp, int err)
 
 static int usblp_open(struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
+       int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
        struct usblp *usblp;
        int retval;
 
index 2e17eabd2d03b9803b2ce24d977fa6c5271a47a7..bf1fdb9681c10625e13d5f33b47d41b1bf1783d6 100644 (file)
@@ -365,7 +365,7 @@ open_scanner(struct inode * inode, struct file * file)
        struct scn_usb_data *scn;
        struct usb_device *dev;
 
-       kdev_t scn_minor;
+       int scn_minor;
 
        int err=0;
 
@@ -432,7 +432,7 @@ close_scanner(struct inode * inode, struct file * file)
 {
        struct scn_usb_data *scn;
 
-       kdev_t scn_minor;
+       int scn_minor;
 
        scn_minor = USB_SCN_MINOR (inode);
 
@@ -469,7 +469,7 @@ write_scanner(struct file * file, const char * buffer,
        ssize_t bytes_written = 0; /* Overall count of bytes written */
        ssize_t ret = 0;
 
-       kdev_t scn_minor;
+       int scn_minor;
 
        int this_write;         /* Number of bytes to write */
        int partial;            /* Number of bytes successfully written */
@@ -556,8 +556,7 @@ read_scanner(struct file * file, char * buffer,
        ssize_t bytes_read;     /* Overall count of bytes_read */
        ssize_t ret;
 
-       kdev_t scn_minor;
-
+       int scn_minor;
        int partial;            /* Number of bytes successfully read */
        int this_read;          /* Max number of bytes to read */
        int result;
@@ -671,7 +670,7 @@ ioctl_scanner(struct inode *inode, struct file *file,
 {
        struct usb_device *dev;
 
-       kdev_t scn_minor;
+       int scn_minor;
 
        scn_minor = USB_SCN_MINOR(inode);
 
@@ -810,8 +809,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
 
        int ep_cnt;
        int ix;
-
-       kdev_t scn_minor;
+       int scn_minor;
 
        char valid_device = 0;
        char have_bulk_in, have_bulk_out, have_intr;
index 2b03ce8f682d647f024832b60537bb0a6ad9d815..f7b9143bc55062a81831c9afcd2aa501ff14abdc 100644 (file)
@@ -203,7 +203,7 @@ MODULE_DEVICE_TABLE (usb, scanner_device_ids);
 #define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
 #define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
 
-#define USB_SCN_MINOR(X) MINOR((X)->i_rdev) - SCN_BASE_MNR
+#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
 
 #ifdef DEBUG
 #define SCN_DEBUG(X) X
@@ -243,7 +243,7 @@ struct scn_usb_data {
        devfs_handle_t devfs;   /* devfs device */
        struct urb scn_irq;
        unsigned int ifnum;     /* Interface number of the USB device */
-       kdev_t scn_minor;       /* Scanner minor - used in disconnect() */
+       int scn_minor;          /* Scanner minor - used in disconnect() */
        unsigned char button;   /* Front panel buffer */
        char isopen;            /* Not zero if the device is open */
        char present;           /* Not zero if device is present */
index 62176c43682a5e4d24871c46b689309b4b80b877..bc8302781fb1fcced88d9df240a75d0b90683285 100644 (file)
@@ -15,6 +15,7 @@ dep_tristate '  USB Digi International AccelePort USB Serial Driver' CONFIG_USB_
 dep_tristate '  USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+dep_tristate '  USB Compaq iPAQ Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
 dep_tristate '  USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
@@ -28,6 +29,7 @@ dep_tristate '  USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SER
    dep_mbool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
    dep_mbool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
 dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KLSI $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
index e12f6295dbc4c160832047dfe53aa9410e438b1c..90c3dedcb0db4bc831025b3d12759d340e96dd8c 100644 (file)
@@ -8,6 +8,7 @@ O_TARGET        := usb-serial.o
 
 obj-$(CONFIG_USB_SERIAL)                        += usbserial.o
 obj-$(CONFIG_USB_SERIAL_VISOR)                 += visor.o
+obj-$(CONFIG_USB_SERIAL_IPAQ)                  += ipaq.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)             += whiteheat.o
 obj-$(CONFIG_USB_SERIAL_FTDI_SIO)              += ftdi_sio.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)           += keyspan_pda.o
@@ -22,7 +23,8 @@ obj-$(CONFIG_USB_SERIAL_EDGEPORT)             += io_edgeport.o
 obj-$(CONFIG_USB_SERIAL_PL2303)                        += pl2303.o
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)             += cyberjack.o
 obj-$(CONFIG_USB_SERIAL_IR)                    += ir-usb.o
+obj-$(CONFIG_USB_SERIAL_KLSI)                  += kl5kusb105.o
+
 # Objects that export symbols.
 export-objs    := usbserial.o
 
index fdd07e6c7d825b79aa2b798593a0a0e5aaf52234..7b476f2f65f77d8dc33adfc4c0c6771c46f43337 100644 (file)
@@ -397,16 +397,16 @@ static struct usb_serial  *serial_table[SERIAL_TTY_MINORS];       /* initially all NULL
 static LIST_HEAD(usb_serial_driver_list);
 
 
-static struct usb_serial *get_serial_by_minor (int minor)
+static struct usb_serial *get_serial_by_minor (unsigned int minor)
 {
        return serial_table[minor];
 }
 
 
-static struct usb_serial *get_free_serial (int num_ports, int *minor)
+static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor)
 {
        struct usb_serial *serial = NULL;
-       int i, j;
+       unsigned int i, j;
        int good_spot;
 
        dbg(__FUNCTION__ " %d", num_ports);
@@ -505,7 +505,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 {
        struct usb_serial *serial;
        struct usb_serial_port *port;
-       int portNumber;
+       unsigned int portNumber;
        
        dbg(__FUNCTION__);
 
@@ -513,14 +513,14 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
        tty->driver_data = NULL;
 
        /* get the serial object associated with this tty pointer */
-       serial = get_serial_by_minor (MINOR(tty->device));
+       serial = get_serial_by_minor (minor(tty->device));
 
        if (serial_paranoia_check (serial, __FUNCTION__)) {
                return -ENODEV;
        }
 
        /* set up our port structure making the tty driver remember our port object, and us it */
-       portNumber = MINOR(tty->device) - serial->minor;
+       portNumber = minor(tty->device) - serial->minor;
        port = &serial->port[portNumber];
        tty->driver_data = port;
        port->tty = tty;
diff --git a/drivers/usb/stv680.c b/drivers/usb/stv680.c
new file mode 100644 (file)
index 0000000..ccba190
--- /dev/null
@@ -0,0 +1,1633 @@
+/*
+ *  STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
+ *  
+ * Thanks to STMicroelectronics for information on the usb commands, and 
+ * to Steve Miller at STM for his help and encouragement while I was 
+ * writing this driver.
+ *
+ * This driver is based heavily on the 
+ * Endpoints (formerly known as AOX) se401 USB Camera Driver
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * Still somewhat based on the Linux ov511 driver.
+ * 
+ * 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.
+ *
+ * History: 
+ * ver 0.1 October, 2001. Initial attempt. 
+ *
+ * ver 0.2 November, 2001. Fixed asbility to resize, added brightness
+ *                         function, made more stable (?)
+ *
+ * ver 0.21 Nov, 2001.     Added gamma correction and white balance, 
+ *                         due to Alexander Schwartz. Still trying to 
+ *                         improve stablility. Moved stuff into stv680.h
+ *
+ * ver 0.22 Nov, 2001.    Added sharpen function (by Michael Sweet, 
+ *                         mike@easysw.com) from GIMP, also used in pencam. 
+ *                         Simple, fast, good integer math routine.
+ *
+ * ver 0.23 Dec, 2001 (gkh)
+ *                        Took out sharpen function, ran code through
+ *                        Lindent, and did other minor tweaks to get
+ *                        things to work properly with 2.5.1
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/wrapper.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/videodev.h>
+#include <linux/usb.h>
+
+#include "stv680.h"
+
+static int video_nr = -1;
+static int swapRGB = 0;
+
+static unsigned int debug = 0;
+
+#define PDEBUG(level, fmt, args...) \
+       do { \
+       if (debug >= level)     \
+               info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args);  \
+       } while (0)
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.23"
+#define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>"
+#define DRIVER_DESC "STV0680 USB Camera Driver"
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_LICENSE ("GPL");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "Debug enabled or not");
+MODULE_PARM (swapRGB, "i");
+MODULE_PARM_DESC (swapRGB, "Swap red and blue, e.g., for xawtv");
+MODULE_PARM (video_nr, "i");
+EXPORT_NO_SYMBOLS;
+
+/********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the ov511 driver -claudio
+ *
+ * Same for the se401 driver -Jeroen
+ *
+ * And the STV0680 driver - Kevin
+ ********************************************************************/
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva (pgd_t * pgd, unsigned long adr)
+{
+       unsigned long ret = 0UL;
+       pmd_t *pmd;
+       pte_t *ptep, pte;
+
+       if (!pgd_none (*pgd)) {
+               pmd = pmd_offset (pgd, adr);
+               if (!pmd_none (*pmd)) {
+                       ptep = pte_offset (pmd, adr);
+                       pte = *ptep;
+                       if (pte_present (pte)) {
+                               ret = (unsigned long) page_address (pte_page (pte));
+                               ret |= (adr & (PAGE_SIZE - 1));
+                       }
+               }
+       }
+       return ret;
+}
+
+/* Here we want the physical address of the memory. This is used when 
+ * initializing the contents of the area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa (unsigned long adr)
+{
+       unsigned long va, kva, ret;
+
+       va = VMALLOC_VMADDR (adr);
+       kva = uvirt_to_kva (pgd_offset_k (va), va);
+       ret = __pa (kva);
+       return ret;
+}
+
+static void *rvmalloc (unsigned long size)
+{
+       void *mem;
+       unsigned long adr, page;
+
+       /* Round it off to PAGE_SIZE */
+       size += (PAGE_SIZE - 1);
+       size &= ~(PAGE_SIZE - 1);
+
+       mem = vmalloc_32 (size);
+       if (!mem)
+               return NULL;
+
+       memset (mem, 0, size);  /* Clear the ram out, no junk to the user */
+       adr = (unsigned long) mem;
+       while (size > 0) {
+               page = kvirt_to_pa (adr);
+               mem_map_reserve (virt_to_page (__va (page)));
+               adr += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+       return mem;
+}
+
+static void rvfree (void *mem, unsigned long size)
+{
+       unsigned long adr, page;
+
+       if (!mem)
+               return;
+
+       size += (PAGE_SIZE - 1);
+       size &= ~(PAGE_SIZE - 1);
+
+       adr = (unsigned long) mem;
+       while (size > 0) {
+               page = kvirt_to_pa (adr);
+               mem_map_unreserve (virt_to_page (__va (page)));
+               adr += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+       vfree (mem);
+}
+
+
+/*********************************************************************
+ * pencam read/write functions
+ ********************************************************************/
+
+static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size)
+{
+       int ret = -1;
+
+       switch (set) {
+       case 0:         /*  0xc1  */
+               ret = usb_control_msg (stv680->udev,
+                                      usb_rcvctrlpipe (stv680->udev, 0),
+                                      req,
+                                      (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+                                      value, 0, buffer, size, PENCAM_TIMEOUT);
+               break;
+
+       case 1:         /*  0x41  */
+               ret = usb_control_msg (stv680->udev,
+                                      usb_sndctrlpipe (stv680->udev, 0),
+                                      req,
+                                      (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+                                      value, 0, buffer, size, PENCAM_TIMEOUT);
+               break;
+
+       case 2:         /*  0x80  */
+               ret = usb_control_msg (stv680->udev,
+                                      usb_rcvctrlpipe (stv680->udev, 0),
+                                      req,
+                                      (USB_DIR_IN | USB_RECIP_DEVICE),
+                                      value, 0, buffer, size, PENCAM_TIMEOUT);
+               break;
+
+       case 3:         /*  0x40  */
+               ret = usb_control_msg (stv680->udev,
+                                      usb_sndctrlpipe (stv680->udev, 0),
+                                      req,
+                                      (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
+                                      value, 0, buffer, size, PENCAM_TIMEOUT);
+               break;
+
+       }
+       if ((ret < 0) && (req != 0x0a)) {
+               PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret);
+       }
+       return ret;
+}
+
+static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate)
+{
+
+       if (usb_set_configuration (dev->udev, configuration) < 0) {
+               PDEBUG (1, "STV(e): FAILED to set configuration %i", configuration);
+               return -1;
+       }
+       if (usb_set_interface (dev->udev, interface, alternate) < 0) {
+               PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate);
+               return -1;
+       }
+       return 0;
+}
+
+static int stv_stop_video (struct usb_stv *dev)
+{
+       int i;
+       unsigned char *buf;
+
+       buf = kmalloc (40, GFP_KERNEL);
+       if (buf == NULL) {
+               PDEBUG (0, "STV(e): Out of (small buf) memory");
+               return -1;
+       }
+
+       /* this is a high priority command; it stops all lower order commands */
+       if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) {
+               i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02);   /* Get Last Error; 2 = busy */
+               PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buf[0], buf[1]);
+       } else {
+               PDEBUG (1, "STV(i): Camera reset to idle mode.");
+       }
+
+       if ((i = stv_set_config (dev, 1, 0, 0)) < 0)
+               PDEBUG (1, "STV(e): Reset config during exit failed");
+
+       /*  get current mode  */
+       buf[0] = 0xf0;
+       if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08)     /* get mode */
+               PDEBUG (0, "STV(e): Stop_video: problem setting original mode");
+       if (dev->origMode != buf[0]) {
+               memset (buf, 0, 8);
+               buf[0] = (unsigned char) dev->origMode;
+               if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) {
+                       PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed");
+                       i = -1;
+               }
+               buf[0] = 0xf0;
+               i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08);
+               if ((i != 0x08) || (buf[0] != dev->origMode)) {
+                       PDEBUG (0, "STV(e): camera NOT set to original resolution.");
+                       i = -1;
+               } else
+                       PDEBUG (0, "STV(i): Camera set to original resolution");
+       }
+       /* origMode */
+       kfree (buf);
+       return i;
+}
+
+static int stv_set_video_mode (struct usb_stv *dev)
+{
+       int i, stop_video = 1;
+       unsigned char *buf;
+
+       buf = kmalloc (40, GFP_KERNEL);
+       if (buf == NULL) {
+               PDEBUG (0, "STV(e): Out of (small buf) memory");
+               return -1;
+       }
+
+       if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
+               kfree (buf);
+               return i;
+       }
+
+       i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12);
+       if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) {
+               PDEBUG (1, "STV(e): Could not get descriptor 0100.");
+               goto error;
+       }
+
+       /*  set alternate interface 1 */
+       if ((i = stv_set_config (dev, 1, 0, 1)) < 0)
+               goto error;
+
+       if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10)
+               goto error;
+       PDEBUG (1, "STV(i): Setting video mode.");
+       /*  Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240)  */
+       if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) {
+               stop_video = 0;
+               goto error;
+       }
+       goto exit;
+
+error:
+       kfree (buf);
+       if (stop_video == 1)
+               stv_stop_video (dev);
+       return -1;
+
+exit:
+       kfree (buf);
+       return 0;
+}
+
+static int stv_init (struct usb_stv *stv680)
+{
+       int i = 0;
+       unsigned char *buffer;
+       unsigned long int bufsize;
+
+       buffer = kmalloc (40, GFP_KERNEL);
+       if (buffer == NULL) {
+               PDEBUG (0, "STV(e): Out of (small buf) memory");
+               return -1;
+       }
+       memset (buffer, 0, 40);
+       udelay (100);
+
+       /* set config 1, interface 0, alternate 0 */
+       if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
+               kfree (buffer);
+               PDEBUG (0, "STV(e): set config 1,0,0 failed");
+               return -1;
+       }
+       /* ping camera to be sure STV0680 is present */
+       if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02)
+               goto error;
+       if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) {
+               PDEBUG (1, "STV(e): camera ping failed!!");
+               goto error;
+       }
+
+       /* get camera descriptor */
+       if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09)
+               goto error;
+       i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22);
+       if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) {
+               PDEBUG (1, "STV(e): Could not get descriptor 0200.");
+               goto error;
+       }
+       if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02)
+               goto error;
+       if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24)
+               goto error;
+       if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+               goto error;
+
+       stv680->SupportedModes = buffer[7];
+       i = stv680->SupportedModes;
+       stv680->CIF = 0;
+       stv680->VGA = 0;
+       stv680->QVGA = 0;
+       if (i & 1)
+               stv680->CIF = 1;
+       if (i & 2)
+               stv680->VGA = 1;
+       if (i & 8)
+               stv680->QVGA = 1;
+       if (stv680->SupportedModes == 0) {
+               PDEBUG (0, "STV(e): There are NO supported STV680 modes!!");
+               i = -1;
+               goto error;
+       } else {
+               if (stv680->CIF)
+                       PDEBUG (0, "STV(i): CIF is supported");
+               if (stv680->QVGA)
+                       PDEBUG (0, "STV(i): QVGA is supported");
+       }
+       /* FW rev, ASIC rev, sensor ID  */
+       PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]);
+       PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]);
+       PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4));
+
+       /*  set alternate interface 1 */
+       if ((i = stv_set_config (stv680, 1, 0, 1)) < 0)
+               goto error;
+
+       if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+               goto error;
+       if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08)
+               goto error;
+       i = buffer[3];
+       PDEBUG (0, "STV(i): Camera has %i pictures.", i);
+
+       /*  get current mode */
+       if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08)
+               goto error;
+       stv680->origMode = buffer[0];   /* 01 = VGA, 03 = QVGA, 00 = CIF */
+
+       /* This will attemp CIF mode, if supported. If not, set to QVGA  */
+       memset (buffer, 0, 8);
+       if (stv680->CIF)
+               buffer[0] = 0x00;
+       else if (stv680->QVGA)
+               buffer[0] = 0x03;
+       if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) {
+               PDEBUG (0, "STV(i): Set_Camera_Mode failed");
+               i = -1;
+               goto error;
+       }
+       buffer[0] = 0xf0;
+       stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08);
+       if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) {
+               PDEBUG (0, "STV(e): Error setting camera video mode!");
+               i = -1;
+               goto error;
+       } else {
+               if (buffer[0] == 0) {
+                       stv680->VideoMode = 0x0000;
+                       PDEBUG (0, "STV(i): Video Mode set to CIF");
+               }
+               if (buffer[0] == 0x03) {
+                       stv680->VideoMode = 0x0300;
+                       PDEBUG (0, "STV(i): Video Mode set to QVGA");
+               }
+       }
+       if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10)
+               goto error;
+       bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]);
+       stv680->cwidth = (buffer[4] << 8) | (buffer[5]);        /* ->camera = 322, 356, 644  */
+       stv680->cheight = (buffer[6] << 8) | (buffer[7]);       /* ->camera = 242, 292, 484  */
+       stv680->origGain = buffer[12];
+
+       goto exit;
+
+error:
+       i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02);     /* Get Last Error */
+       PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buffer[0], buffer[1]);
+       kfree (buffer);
+       return -1;
+
+exit:
+       kfree (buffer);
+
+       /* video = 320x240, 352x288 */
+       if (stv680->CIF == 1) {
+               stv680->maxwidth = 352;
+               stv680->maxheight = 288;
+               stv680->vwidth = 352;
+               stv680->vheight = 288;
+       }
+       if (stv680->QVGA == 1) {
+               stv680->maxwidth = 320;
+               stv680->maxheight = 240;
+               stv680->vwidth = 320;
+               stv680->vheight = 240;
+       }
+
+       stv680->rawbufsize = bufsize;   /* must be ./. by 8 */
+       stv680->maxframesize = bufsize * 3;     /* RGB size */
+       PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight);
+       PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize);
+
+       /* some default values */
+       stv680->bulk_in_endpointAddr = 0x82;
+       stv680->dropped = 0;
+       stv680->error = 0;
+       stv680->framecount = 0;
+       stv680->readcount = 0;
+       stv680->streaming = 0;
+       /* bright, white, colour, hue, contrast are set by software, not in stv0680 */
+       stv680->brightness = 32767;
+       stv680->chgbright = 0;
+       stv680->whiteness = 0;  /* only for greyscale */
+       stv680->colour = 32767;
+       stv680->contrast = 32767;
+       stv680->hue = 32767;
+       stv680->palette = STV_VIDEO_PALETTE;
+       stv680->depth = 24;     /* rgb24 bits */
+       swapRGB = 0;
+       PDEBUG (1, "STV(i): swapRGB is OFF");
+
+       if (stv_set_video_mode (stv680) < 0) {
+               PDEBUG (0, "STV(e): Could not set video mode in stv_init");
+               return -1;
+       }
+
+       return 0;
+}
+
+/***************** last of pencam  routines  *******************/
+
+/********************************************************************
+ * /proc interface
+ *******************************************************************/
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+static struct proc_dir_entry *stv680_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
+
+#define YES_NO(x) ((x) ? "yes" : "no")
+
+static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       char *out = page;
+       int len;
+       struct usb_stv *stv680 = data;
+
+       /* Stay under PAGE_SIZE or else bla bla bla.... */
+
+       out += sprintf (out, "driver_version  : %s\n", DRIVER_VERSION);
+       out += sprintf (out, "model           : %s\n", stv680->camera_name);
+       out += sprintf (out, "in use          : %s\n", YES_NO (stv680->user));
+       out += sprintf (out, "streaming       : %s\n", YES_NO (stv680->streaming));
+       out += sprintf (out, "num_frames      : %d\n", STV680_NUMFRAMES);
+
+       out += sprintf (out, "Current size    : %ix%i\n", stv680->vwidth, stv680->vheight);
+       out += sprintf (out, "swapRGB         : %s\n", YES_NO (swapRGB));
+       out += sprintf (out, "Palette         : %i", stv680->palette);
+
+       out += sprintf (out, "\n");
+
+       out += sprintf (out, "Frames total    : %d\n", stv680->readcount);
+       out += sprintf (out, "Frames read     : %d\n", stv680->framecount);
+       out += sprintf (out, "Packets dropped : %d\n", stv680->dropped);
+       out += sprintf (out, "Decoding Errors : %d\n", stv680->error);
+
+       len = out - page;
+       len -= off;
+       if (len < count) {
+               *eof = 1;
+               if (len <= 0)
+                       return 0;
+       } else
+               len = count;
+
+       *start = page + off;
+       return len;
+}
+
+static int create_proc_stv680_cam (struct usb_stv *stv680)
+{
+       char name[9];
+       struct proc_dir_entry *ent;
+
+       if (!stv680_proc_entry || !stv680)
+               return -1;
+
+       sprintf (name, "video%d", stv680->vdev.minor);
+
+       ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, stv680_proc_entry);
+       if (!ent)
+               return -1;
+
+       ent->data = stv680;
+       ent->read_proc = stv680_read_proc;
+       stv680->proc_entry = ent;
+       return 0;
+}
+
+static void destroy_proc_stv680_cam (struct usb_stv *stv680)
+{
+       /* One to much, just to be sure :) */
+       char name[9];
+
+       if (!stv680 || !stv680->proc_entry)
+               return;
+
+       sprintf (name, "video%d", stv680->vdev.minor);
+       remove_proc_entry (name, stv680_proc_entry);
+       stv680->proc_entry = NULL;
+}
+
+static int proc_stv680_create (void)
+{
+       if (video_proc_entry == NULL) {
+               PDEBUG (0, "STV(e): /proc/video/ doesn't exist!");
+               return -1;
+       }
+       stv680_proc_entry = create_proc_entry ("stv680", S_IFDIR, video_proc_entry);
+
+       if (stv680_proc_entry) {
+               stv680_proc_entry->owner = THIS_MODULE;
+       } else {
+               PDEBUG (0, "STV(e): Unable to initialize /proc/video/stv680");
+               return -1;
+       }
+       return 0;
+}
+
+static void proc_stv680_destroy (void)
+{
+       if (stv680_proc_entry == NULL)
+               return;
+
+       remove_proc_entry ("stv", video_proc_entry);
+}
+#endif                         /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+/********************************************************************
+ * Camera control
+ *******************************************************************/
+
+static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+       /* This sets values for v4l interface. max/min = 65535/0  */
+
+       p->brightness = stv680->brightness;
+       p->whiteness = stv680->whiteness;       /* greyscale */
+       p->colour = stv680->colour;
+       p->contrast = stv680->contrast;
+       p->hue = stv680->hue;
+       p->palette = stv680->palette;
+       p->depth = stv680->depth;
+       return 0;
+}
+
+static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+       /* See above stv680_get_pict  */
+
+       if (p->palette != STV_VIDEO_PALETTE) {
+               PDEBUG (2, "STV(e): Palette set error in _set_pic");
+               return 1;
+       }
+
+       if (stv680->brightness != p->brightness) {
+               stv680->chgbright = 1;
+               stv680->brightness = p->brightness;
+       } else {
+               stv680->chgbright = 0;
+       }
+
+       stv680->whiteness = p->whiteness;       /* greyscale */
+       stv680->colour = p->colour;
+       stv680->contrast = p->contrast;
+       stv680->hue = p->hue;
+       stv680->palette = p->palette;
+       stv680->depth = p->depth;
+
+       return 0;
+}
+
+static void stv680_video_irq (struct urb *urb)
+{
+       struct usb_stv *stv680 = urb->context;
+       int length = urb->actual_length;
+
+       if (length < stv680->rawbufsize)
+               PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length);
+
+       /* ohoh... */
+       if (!stv680->streaming)
+               return;
+
+       if (!stv680->udev) {
+               PDEBUG (0, "STV(e): device vapourished in video_irq");
+               return;
+       }
+
+       /* 0 sized packets happen if we are to fast, but sometimes the camera
+          keeps sending them forever...
+        */
+       if (length && !urb->status) {
+               stv680->nullpackets = 0;
+               switch (stv680->scratch[stv680->scratch_next].state) {
+               case BUFFER_READY:
+               case BUFFER_BUSY:
+                       stv680->dropped++;
+                       break;
+
+               case BUFFER_UNUSED:
+                       memcpy (stv680->scratch[stv680->scratch_next].data,
+                               (unsigned char *) urb->transfer_buffer, length);
+                       stv680->scratch[stv680->scratch_next].state = BUFFER_READY;
+                       stv680->scratch[stv680->scratch_next].length = length;
+                       if (waitqueue_active (&stv680->wq)) {
+                               wake_up_interruptible (&stv680->wq);
+                       }
+                       stv680->scratch_overflow = 0;
+                       stv680->scratch_next++;
+                       if (stv680->scratch_next >= STV680_NUMSCRATCH)
+                               stv680->scratch_next = 0;;
+                       break;
+               }               /* switch  */
+       } else {
+               stv680->nullpackets++;
+               if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+                       if (waitqueue_active (&stv680->wq)) {
+                               wake_up_interruptible (&stv680->wq);
+                       }
+               }
+       }                       /*  if - else */
+
+       /* Resubmit urb for new data */
+       urb->status = 0;
+       urb->dev = stv680->udev;
+       if (usb_submit_urb (urb))
+               PDEBUG (0, "STV(e): urb burned down in video irq");
+       return;
+}                              /*  _video_irq  */
+
+static int stv680_start_stream (struct usb_stv *stv680)
+{
+       urb_t *urb;
+       int err = 0, i;
+
+       stv680->streaming = 1;
+
+       /* Do some memory allocation */
+       for (i = 0; i < STV680_NUMFRAMES; i++) {
+               stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize;
+               stv680->frame[i].curpix = 0;
+       }
+       /* packet size = 4096  */
+       for (i = 0; i < STV680_NUMSBUF; i++) {
+               stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+               if (stv680->sbuf[i].data == NULL) {
+                       PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
+                       return -1;
+               }
+       }
+
+       stv680->scratch_next = 0;
+       stv680->scratch_use = 0;
+       stv680->scratch_overflow = 0;
+       for (i = 0; i < STV680_NUMSCRATCH; i++) {
+               stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+               if (stv680->scratch[i].data == NULL) {
+                       PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
+                       return -1;
+               }
+               stv680->scratch[i].state = BUFFER_UNUSED;
+       }
+
+       for (i = 0; i < STV680_NUMSBUF; i++) {
+               urb = usb_alloc_urb (0);
+               if (!urb)
+                       return ENOMEM;
+
+               /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
+               usb_fill_bulk_urb (urb, stv680->udev,
+                                  usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
+                                  stv680->sbuf[i].data, stv680->rawbufsize,
+                                  stv680_video_irq, stv680);
+               urb->timeout = PENCAM_TIMEOUT * 2;
+               urb->transfer_flags |= USB_QUEUE_BULK;
+               stv680->urb[i] = urb;
+               err = usb_submit_urb (stv680->urb[i]);
+               if (err)
+                       PDEBUG (0, "STV(e): urb burned down in start stream");
+       }                       /* i STV680_NUMSBUF */
+
+       stv680->framecount = 0;
+       return 0;
+}
+
+static int stv680_stop_stream (struct usb_stv *stv680)
+{
+       int i;
+
+       if (!stv680->streaming || !stv680->udev)
+               return 1;
+
+       stv680->streaming = 0;
+
+       for (i = 0; i < STV680_NUMSBUF; i++)
+               if (stv680->urb[i]) {
+                       stv680->urb[i]->next = NULL;
+                       usb_unlink_urb (stv680->urb[i]);
+                       usb_free_urb (stv680->urb[i]);
+                       stv680->urb[i] = NULL;
+                       kfree (stv680->sbuf[i].data);
+               }
+       for (i = 0; i < STV680_NUMSCRATCH; i++) {
+               kfree (stv680->scratch[i].data);
+               stv680->scratch[i].data = NULL;
+       }
+
+       return 0;
+}
+
+static int stv680_set_size (struct usb_stv *stv680, int width, int height)
+{
+       int wasstreaming = stv680->streaming;
+
+       /* Check to see if we need to change */
+       if ((stv680->vwidth == width) && (stv680->vheight == height))
+               return 0;
+
+       PDEBUG (1, "STV(i): size request for %i x %i", width, height);
+       /* Check for a valid mode */
+       if ((!width || !height) || ((width & 1) || (height & 1))) {
+               PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
+               return 1;
+       }
+
+       if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {
+               width = stv680->maxwidth / 2;
+               height = stv680->maxheight / 2;
+       } else if ((width >= 158) && (width <= 166)) {
+               width = 160;
+               height = 120;
+       } else if ((width >= 172) && (width <= 180)) {
+               width = 176;
+               height = 144;
+       } else if ((width >= 318) && (width <= 350)) {
+               width = 320;
+               height = 240;
+       } else if ((width >= 350) && (width <= 358)) {
+               width = 352;
+               height = 288;
+       }
+
+       /* Stop a current stream and start it again at the new size */
+       if (wasstreaming)
+               stv680_stop_stream (stv680);
+       stv680->vwidth = width;
+       stv680->vheight = height;
+       PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight);
+       if (wasstreaming)
+               stv680_start_stream (stv680);
+
+       return 0;
+}
+
+/**********************************************************************
+ * Video Decoding
+ **********************************************************************/
+
+/*******  routines from the pencam program; hey, they work!  ********/
+
+/*
+ * STV0680 Vision Camera Chipset Driver
+ * Copyright (C) 2000 Adam Harrison <adam@antispin.org> 
+*/
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define AD(x, y, w) (((y)*(w)+(x))*3)
+
+static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer)
+{
+       int x, y, i;
+       int w = stv680->cwidth;
+       int vw = stv680->cwidth, vh = stv680->cheight, vstep = 1;
+       unsigned int p = 0;
+       int colour = 0, bayer = 0;
+       unsigned char *raw = buffer->data;
+       struct stv680_frame *frame = &stv680->frame[stv680->curframe];
+       unsigned char *output = frame->data;
+       unsigned char *temp = frame->data;
+       int offset = buffer->offset;
+
+       if (frame->curpix == 0) {
+               if (frame->grabstate == FRAME_READY) {
+                       frame->grabstate = FRAME_GRABBING;
+               }
+       }
+       if (offset != frame->curpix) {  /* Regard frame as lost :( */
+               frame->curpix = 0;
+               stv680->error++;
+               return;
+       }
+
+       if ((stv680->vwidth == 322) || (stv680->vwidth == 320)) {
+               vw = 320;
+               vh = 240;
+               vstep = 1;
+       }
+       if ((stv680->vwidth == 352)) {
+               vw = 352;
+               vh = 288;
+               vstep = 1;
+       }
+       if ((stv680->vwidth == 160)) {
+               vw = 160;
+               vh = 120;
+               vstep = 2;
+       }
+       if ((stv680->vwidth == 176)) {
+               vw = 176;
+               vh = 144;
+               vstep = 2;
+       }
+       memset (output, 0, 3 * vw * vh);        /* clear output matrix. Maybe not necessary. */
+
+       for (y = 0; y < vh; y++) {
+               for (x = 0; x < vw; x++) {
+
+                       switch (vstep) {
+                       case 1:
+                               if (x & 1)
+                                       p = *(raw + y * w + (x >> 1));
+                               else
+                                       p = *(raw + y * w + (x >> 1) + (w >> 1));
+                               break;
+
+                       case 2:
+                               if (x & 1)
+                                       p = *(raw + ((y * w) << 1) + x);
+                               else
+                                       p = *(raw + ((y * w) << 1) + x + (w >> 1));
+                               break;
+                       }
+
+                       if (y & 1)
+                               bayer = 2;
+                       else
+                               bayer = 0;
+                       if (x & 1)
+                               bayer++;
+
+                       switch (bayer) {
+                       case 0:
+                       case 3:
+                               colour = 1;
+                               break;
+                       case 1:
+                               colour = 0;
+                               break;
+                       case 2:
+                               colour = 2;
+                               break;
+                       }
+                       i = (y * vw + x) * 3;   /* output already zeroed out with memset */
+                       *(output + i + colour) = (unsigned char) p;
+               }               /* for x */
+       }                       /* for y */
+
+       /****** gamma correction plus hardcoded white balance */
+       /* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
+          Correction values red[], green[], blue[], are generated by 
+          (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255. 
+          White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and 
+          converted to unsigned char. Values are in stv680.h  */
+       for (y = 0; y < vh; y++) {
+               for (x = 0; x < vw; x++) {
+                       i = (y * vw + x) * 3;
+                       *(output + i) = red[*(output + i)];
+                       *(output + i + 1) = green[*(output + i + 1)];
+                       *(output + i + 2) = blue[*(output + i + 2)];
+               }
+       }
+
+       /******  bayer demosaic  ******/
+       for (y = 1; y < (vh - 1); y++) {
+               for (x = 1; x < (vw - 1); x++) {        /* work out pixel type */
+                       if (y & 1)
+                               bayer = 0;
+                       else
+                               bayer = 2;
+                       if (!(x & 1))
+                               bayer++;
+
+                       switch (bayer) {
+                       case 0: /* green. blue lr, red tb */
+                               *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1;
+                               *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1;
+                               break;
+
+                       case 1: /* blue. green lrtb, red diagonals */
+                               *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+                               *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2;
+                               break;
+
+                       case 2: /* red. green lrtb, blue diagonals */
+                               *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+                               *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2;
+                               break;
+
+                       case 3: /* green. red lr, blue tb */
+                               *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1;
+                               *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1;
+                               break;
+                       }       /* switch */
+               }               /* for x */
+       }                       /* for y  - end demosaic  */
+
+       /* output is RGB; some programs want BGR  */
+       if (swapRGB == 1) {
+               for (y = 0; y < vh; y++) {
+                       for (x = 0; x < vw; x++) {
+                               i = (y * vw + x) * 3;
+                               *(temp) = *(output + i);
+                               *(output + i) = *(output + i + 2);
+                               *(output + i + 2) = *(temp);
+                       }
+               }
+       }
+       /* brightness */
+       if (stv680->chgbright == 1) {
+               if (stv680->brightness >= 32767) {
+                       p = (stv680->brightness - 32767) / 256;
+                       for (x = 0; x < (vw * vh * 3); x++) {
+                               if ((*(output + x) + (unsigned char) p) > 255)
+                                       *(output + x) = 255;
+                               else
+                                       *(output + x) += (unsigned char) p;
+                       }       /* for */
+               } else {
+                       p = (32767 - stv680->brightness) / 256;
+                       for (x = 0; x < (vw * vh * 3); x++) {
+                               if ((unsigned char) p > *(output + x))
+                                       *(output + x) = 0;
+                               else
+                                       *(output + x) -= (unsigned char) p;
+                       }       /* for */
+               }               /* else */
+       }
+       /* if */
+       frame->curpix = 0;
+       frame->curlinepix = 0;
+       frame->grabstate = FRAME_DONE;
+       stv680->framecount++;
+       stv680->readcount++;
+       if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) {
+               stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1);
+       }
+
+}                              /* bayer_unshuffle */
+
+/*******  end routines from the pencam program  *********/
+
+static int stv680_newframe (struct usb_stv *stv680, int framenr)
+{
+       int errors = 0;
+
+       while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) {
+               if (!stv680->frame[framenr].curpix) {
+                       errors++;
+               }
+               wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY));
+
+               if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+                       stv680->nullpackets = 0;
+                       PDEBUG (2, "STV(i): too many null length packets, restarting capture");
+                       stv680_stop_stream (stv680);
+                       stv680_start_stream (stv680);
+               } else {
+                       if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) {
+                               stv680->frame[framenr].grabstate = FRAME_ERROR;
+                               PDEBUG (2, "STV(e): FRAME_ERROR in _newframe");
+                               return -EIO;
+                       }
+                       stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY;
+
+                       bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]);
+
+                       stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;
+                       stv680->scratch_use++;
+                       if (stv680->scratch_use >= STV680_NUMSCRATCH)
+                               stv680->scratch_use = 0;
+                       if (errors > STV680_MAX_ERRORS) {
+                               errors = 0;
+                               PDEBUG (2, "STV(i): too many errors, restarting capture");
+                               stv680_stop_stream (stv680);
+                               stv680_start_stream (stv680);
+                       }
+               }               /* else */
+       }                       /* while */
+       return 0;
+}
+
+/*********************************************************************
+ * Video4Linux
+ *********************************************************************/
+
+static int stv_open (struct video_device *dev, int flags)
+{
+       struct usb_stv *stv680 = (struct usb_stv *) dev;
+       int err = 0;
+
+       /* we are called with the BKL held */
+       MOD_INC_USE_COUNT;
+       stv680->user = 1;
+       err = stv_init (stv680);        /* main initialization routine for camera */
+
+       if (err >= 0) {
+               stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);
+               if (!stv680->fbuf) {
+                       PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");
+                       err = -ENOMEM;
+               }
+       }
+       if (err) {
+               MOD_DEC_USE_COUNT;
+               stv680->user = 0;
+       }
+
+       return err;
+}
+
+static void stv_close (struct video_device *dev)
+{
+       /* called with BKL held */
+       struct usb_stv *stv680 = (struct usb_stv *) dev;
+       int i;
+
+       for (i = 0; i < STV680_NUMFRAMES; i++)
+               stv680->frame[i].grabstate = FRAME_UNUSED;
+       if (stv680->streaming)
+               stv680_stop_stream (stv680);
+
+       if ((i = stv_stop_video (stv680)) < 0)
+               PDEBUG (1, "STV(e): stop_video failed in stv_close");
+
+       rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);
+       stv680->user = 0;
+
+       if (stv680->removed) {
+               video_unregister_device (&stv680->vdev);
+               kfree (stv680);
+               stv680 = NULL;
+               PDEBUG (0, "STV(i): device unregistered");
+       }
+       MOD_DEC_USE_COUNT;
+}
+
+static long stv680_write (struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+       return -EINVAL;
+}
+
+static int stv680_ioctl (struct video_device *vdev, unsigned int cmd, void *arg)
+{
+       struct usb_stv *stv680 = (struct usb_stv *) vdev;
+
+       if (!stv680->udev)
+               return -EIO;
+
+       switch (cmd) {
+       case VIDIOCGCAP:{
+                       struct video_capability b;
+
+                       strcpy (b.name, stv680->camera_name);
+                       b.type = VID_TYPE_CAPTURE;
+                       b.channels = 1;
+                       b.audios = 0;
+                       b.maxwidth = stv680->maxwidth;
+                       b.maxheight = stv680->maxheight;
+                       b.minwidth = stv680->maxwidth / 2;
+                       b.minheight = stv680->maxheight / 2;
+
+                       if (copy_to_user (arg, &b, sizeof (b))) {
+                               PDEBUG (2, "STV(e): VIDIOCGGAP failed");
+                               return -EFAULT;
+                       }
+                       return 0;
+               }
+       case VIDIOCGCHAN:{
+                       struct video_channel v;
+
+                       if (copy_from_user (&v, arg, sizeof (v)))
+                               return -EFAULT;
+                       if (v.channel != 0)
+                               return -EINVAL;
+
+                       v.flags = 0;
+                       v.tuners = 0;
+                       v.type = VIDEO_TYPE_CAMERA;
+                       strcpy (v.name, "STV Camera");
+
+                       if (copy_to_user (arg, &v, sizeof (v))) {
+                               PDEBUG (2, "STV(e): VIDIOCGCHAN failed");
+                               return -EFAULT;
+                       }
+                       return 0;
+               }
+       case VIDIOCSCHAN:{
+                       int v;
+
+                       if (copy_from_user (&v, arg, sizeof (v))) {
+                               PDEBUG (2, "STV(e): VIDIOCSCHAN failed");
+                               return -EFAULT;
+                       }
+                       if (v != 0)
+                               return -EINVAL;
+
+                       return 0;
+               }
+       case VIDIOCGPICT:{
+                       struct video_picture p;
+
+                       stv680_get_pict (stv680, &p);
+                       if (copy_to_user (arg, &p, sizeof (p))) {
+                               PDEBUG (2, "STV(e): VIDIOCGPICT failed");
+                               return -EFAULT;
+                       }
+                       return 0;
+               }
+       case VIDIOCSPICT:{
+                       struct video_picture p;
+
+                       if (copy_from_user (&p, arg, sizeof (p))) {
+                               PDEBUG (2, "STV(e): VIDIOCSPICT failed");
+                               return -EFAULT;
+                       }
+                       copy_from_user (&p, arg, sizeof (p));
+                       PDEBUG (2, "STV(i): palette set to RGB in VIDIOSPICT");
+
+                       if (stv680_set_pict (stv680, &p))
+                               return -EINVAL;
+                       return 0;
+               }
+       case VIDIOCSWIN:{
+                       struct video_window vw;
+
+                       if (copy_from_user (&vw, arg, sizeof (vw)))
+                               return -EFAULT;
+                       if (vw.flags)
+                               return -EINVAL;
+                       if (vw.clipcount)
+                               return -EINVAL;
+                       if (vw.width != stv680->vwidth) {
+                               if (stv680_set_size (stv680, vw.width, vw.height)) {
+                                       PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN");
+                                       return -EINVAL;
+                               }
+                       }
+                       return 0;
+               }
+       case VIDIOCGWIN:{
+                       struct video_window vw;
+
+                       vw.x = 0;       /* FIXME */
+                       vw.y = 0;
+                       vw.chromakey = 0;
+                       vw.flags = 0;
+                       vw.clipcount = 0;
+                       vw.width = stv680->vwidth;
+                       vw.height = stv680->vheight;
+
+                       if (copy_to_user (arg, &vw, sizeof (vw))) {
+                               PDEBUG (2, "STV(e): VIDIOCGWIN failed");
+                               return -EFAULT;
+                       }
+                       return 0;
+               }
+       case VIDIOCGMBUF:{
+                       struct video_mbuf vm;
+                       int i;
+
+                       memset (&vm, 0, sizeof (vm));
+                       vm.size = STV680_NUMFRAMES * stv680->maxframesize;
+                       vm.frames = STV680_NUMFRAMES;
+                       for (i = 0; i < STV680_NUMFRAMES; i++)
+                               vm.offsets[i] = stv680->maxframesize * i;
+
+                       if (copy_to_user ((void *) arg, (void *) &vm, sizeof (vm))) {
+                               PDEBUG (2, "STV(e): VIDIOCGMBUF failed");
+                               return -EFAULT;
+                       }
+
+                       return 0;
+               }
+       case VIDIOCMCAPTURE:{
+                       struct video_mmap vm;
+
+                       if (copy_from_user (&vm, arg, sizeof (vm))) {
+                               PDEBUG (2, "STV(e): VIDIOCMCAPTURE failed");
+                               return -EFAULT;
+                       }
+                       if (vm.format != STV_VIDEO_PALETTE) {
+                               PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",
+                                       vm.format, STV_VIDEO_PALETTE);
+                               if (vm.format == 3) {
+                                       PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is ON");
+                                       /* this may fix those apps (e.g., xawtv) that want BGR */
+                                       swapRGB = 1;
+                               }
+                               return -EINVAL;
+                       }
+                       if (vm.frame >= STV680_NUMFRAMES) {
+                               PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");
+                               return -EINVAL;
+                       }
+                       if (stv680->frame[vm.frame].grabstate != FRAME_UNUSED) {
+                               PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate != FRAME_UNUSED");
+                               return -EBUSY;
+                       }
+                       /* Is this according to the v4l spec??? */
+                       if (stv680->vwidth != vm.width) {
+                               if (stv680_set_size (stv680, vm.width, vm.height)) {
+                                       PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed");
+                                       return -EINVAL;
+                               }
+                       }
+                       stv680->frame[vm.frame].grabstate = FRAME_READY;
+
+                       if (!stv680->streaming)
+                               stv680_start_stream (stv680);
+
+                       return 0;
+               }
+       case VIDIOCSYNC:{
+                       int frame, ret = 0;
+
+                       if (copy_from_user ((void *) &frame, arg, sizeof (int))) {
+                               PDEBUG (2, "STV(e): VIDIOCSYNC failed");
+                               return -EFAULT;
+                       }
+                       if (frame < 0 || frame >= STV680_NUMFRAMES) {
+                               PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC");
+                               return -EINVAL;
+                       }
+                       ret = stv680_newframe (stv680, frame);
+                       stv680->frame[frame].grabstate = FRAME_UNUSED;
+                       return ret;
+               }
+       case VIDIOCGFBUF:{
+                       struct video_buffer vb;
+
+                       memset (&vb, 0, sizeof (vb));
+                       vb.base = NULL; /* frame buffer not supported, not used */
+
+                       if (copy_to_user ((void *) arg, (void *) &vb, sizeof (vb))) {
+                               PDEBUG (2, "STV(e): VIDIOCSYNC failed");
+                               return -EFAULT;
+                       }
+                       return 0;
+               }
+       case VIDIOCKEY:
+               return 0;
+       case VIDIOCCAPTURE:
+               {
+                       PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");
+                       return -EINVAL;
+               }
+       case VIDIOCSFBUF:
+               return -EINVAL;
+       case VIDIOCGTUNER:
+       case VIDIOCSTUNER:
+               return -EINVAL;
+       case VIDIOCGFREQ:
+       case VIDIOCSFREQ:
+               return -EINVAL;
+       case VIDIOCGAUDIO:
+       case VIDIOCSAUDIO:
+               return -EINVAL;
+       default:
+               return -ENOIOCTLCMD;
+       }                       /* end switch */
+
+       return 0;
+}
+
+static int stv680_mmap (struct video_device *dev, const char *adr, unsigned long size)
+{
+       struct usb_stv *stv680 = (struct usb_stv *) dev;
+       unsigned long start = (unsigned long) adr;
+       unsigned long page, pos;
+
+       down (&stv680->lock);
+
+       if (stv680->udev == NULL) {
+               up (&stv680->lock);
+               return -EIO;
+       }
+       if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
+                   & ~(PAGE_SIZE - 1))) {
+               up (&stv680->lock);
+               return -EINVAL;
+       }
+       pos = (unsigned long) stv680->fbuf;
+       while (size > 0) {
+               page = kvirt_to_pa (pos);
+               if (remap_page_range (start, page, PAGE_SIZE, PAGE_SHARED)) {
+                       up (&stv680->lock);
+                       return -EAGAIN;
+               }
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+       up (&stv680->lock);
+
+       return 0;
+}
+
+static long stv680_read (struct video_device *dev, char *buf, unsigned long count, int noblock)
+{
+       unsigned long int realcount = count;
+       int ret = 0;
+       struct usb_stv *stv680 = (struct usb_stv *) dev;
+       unsigned long int i;
+
+       if (STV680_NUMFRAMES != 2) {
+               PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!");
+               return -1;
+       }
+       if (stv680->udev == NULL)
+               return -EIO;
+       if (realcount > (stv680->vwidth * stv680->vheight * 3))
+               realcount = stv680->vwidth * stv680->vheight * 3;
+
+       /* Shouldn't happen: */
+       if (stv680->frame[0].grabstate == FRAME_GRABBING) {
+               PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read");
+               return -EBUSY;
+       }
+       stv680->frame[0].grabstate = FRAME_READY;
+       stv680->frame[1].grabstate = FRAME_UNUSED;
+       stv680->curframe = 0;
+
+       if (!stv680->streaming)
+               stv680_start_stream (stv680);
+
+       if (!stv680->streaming) {
+               ret = stv680_newframe (stv680, 0);      /* ret should = 0 */
+       }
+
+       ret = stv680_newframe (stv680, 0);
+
+       if (!ret) {
+               if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) {
+                       PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i);
+                       return -EFAULT;
+               }
+       } else {
+               realcount = ret;
+       }
+       stv680->frame[0].grabstate = FRAME_UNUSED;
+       return realcount;
+}                              /* stv680_read */
+
+static int stv_init_done (struct video_device *dev)
+{
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       if (create_proc_stv680_cam ((struct usb_stv *) dev) < 0)
+               return -1;
+#endif
+       return 0;
+}
+
+static struct video_device stv680_template = {
+       owner:          THIS_MODULE,
+       name:           "STV0680 USB camera",
+       type:           VID_TYPE_CAPTURE,
+       hardware:       VID_HARDWARE_SE401,
+       open:           stv_open,
+       close:          stv_close,
+       read:           stv680_read,
+       write:          stv680_write,
+       ioctl:          stv680_ioctl,
+       mmap:           stv680_mmap,
+       initialize:     stv_init_done,
+};
+
+static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+{
+       struct usb_interface_descriptor *interface;
+       struct usb_stv *stv680;
+       char *camera_name = NULL;
+
+       /* We don't handle multi-config cameras */
+       if (dev->descriptor.bNumConfigurations != 1) {
+               PDEBUG (0, "STV(e): Number of Configurations != 1");
+               return NULL;
+       }
+
+       interface = &dev->actconfig->interface[ifnum].altsetting[0];
+       /* Is it a STV680? */
+       if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {
+               camera_name = "STV0680";
+               PDEBUG (0, "STV(i): STV0680 camera found.");
+       } else {
+               PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");
+               PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");
+               return NULL;
+       }
+       /* We found one */
+       if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
+               PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");
+               return NULL;
+       }
+
+       memset (stv680, 0, sizeof (*stv680));
+
+       stv680->udev = dev;
+       stv680->camera_name = camera_name;
+
+       memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template));
+       memcpy (stv680->vdev.name, stv680->camera_name, strlen (stv680->camera_name));
+       init_waitqueue_head (&stv680->wq);
+       init_MUTEX (&stv680->lock);
+       wmb ();
+
+       if (video_register_device (&stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+               kfree (stv680);
+               PDEBUG (0, "STV(e): video_register_device failed");
+               return NULL;
+       }
+       PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);
+
+       return stv680;
+}
+
+static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
+{
+       int i;
+
+       stv680->udev = NULL;
+       stv680->frame[0].grabstate = FRAME_ERROR;
+       stv680->frame[1].grabstate = FRAME_ERROR;
+       stv680->streaming = 0;
+
+       wake_up_interruptible (&stv680->wq);
+
+       for (i = 0; i < STV680_NUMSBUF; i++)
+               if (stv680->urb[i]) {
+                       stv680->urb[i]->next = NULL;
+                       usb_unlink_urb (stv680->urb[i]);
+                       usb_free_urb (stv680->urb[i]);
+                       stv680->urb[i] = NULL;
+                       kfree (stv680->sbuf[i].data);
+               }
+       for (i = 0; i < STV680_NUMSCRATCH; i++)
+               if (stv680->scratch[i].data) {
+                       kfree (stv680->scratch[i].data);
+               }
+       PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       destroy_proc_stv680_cam (stv680);
+#endif
+       /* Free the memory */
+       kfree (stv680);
+}
+
+static void stv680_disconnect (struct usb_device *dev, void *ptr)
+{
+       struct usb_stv *stv680 = (struct usb_stv *) ptr;
+
+       lock_kernel ();
+       /* We don't want people trying to open up the device */
+       if (!stv680->user) {
+               video_unregister_device (&stv680->vdev);
+               usb_stv680_remove_disconnected (stv680);
+       } else {
+               stv680->removed = 1;
+       }
+       unlock_kernel ();
+}
+
+static struct usb_driver stv680_driver = {
+       name:           "stv680",
+       probe:          stv680_probe,
+       disconnect:     stv680_disconnect,
+       id_table:       device_table
+};
+
+/********************************************************************
+ *  Module routines
+ ********************************************************************/
+
+static int __init usb_stv680_init (void)
+{
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       if (proc_stv680_create () < 0)
+               return -1;
+#endif
+       if (usb_register (&stv680_driver) < 0) {
+               PDEBUG (0, "STV(e): Could not setup STV0680 driver");
+               return -1;
+       }
+       PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
+
+       info(DRIVER_DESC " " DRIVER_VERSION);
+       return 0;
+}
+
+static void __exit usb_stv680_exit (void)
+{
+       usb_deregister (&stv680_driver);
+       PDEBUG (0, "STV(i): driver deregistered");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+       proc_stv680_destroy ();
+#endif
+}
+
+module_init (usb_stv680_init);
+module_exit (usb_stv680_exit);
diff --git a/drivers/usb/stv680.h b/drivers/usb/stv680.h
new file mode 100644 (file)
index 0000000..74abaab
--- /dev/null
@@ -0,0 +1,222 @@
+/****************************************************************************
+ *
+ *  Filename: stv680.h
+ *
+ *  Description:
+ *     This is a USB driver for STV0680 based usb video cameras.
+ *
+ *  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.
+ *
+ ****************************************************************************/
+
+/* size of usb transfers */
+#define STV680_PACKETSIZE      4096
+
+/* number of queued bulk transfers to use, may have problems if > 1 */
+#define STV680_NUMSBUF         1
+
+/* number of frames supported by the v4l part */
+#define STV680_NUMFRAMES       2
+
+/* scratch buffers for passing data to the decoders: 2 or 4 are good */
+#define STV680_NUMSCRATCH      2
+
+/* number of nul sized packets to receive before kicking the camera */
+#define STV680_MAX_NULLPACKETS 200
+
+/* number of decoding errors before kicking the camera */
+#define STV680_MAX_ERRORS      100
+
+#define USB_PENCAM_VENDOR_ID   0x0553
+#define USB_PENCAM_PRODUCT_ID  0x0202
+#define PENCAM_TIMEOUT          1000
+/* fmt 4 */
+#define STV_VIDEO_PALETTE    VIDEO_PALETTE_RGB24
+
+static __devinitdata struct usb_device_id device_table[] = {
+       {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)},
+       {}
+};
+MODULE_DEVICE_TABLE (usb, device_table);
+
+struct stv680_sbuf {
+       unsigned char *data;
+};
+
+enum {
+       FRAME_UNUSED,           /* Unused (no MCAPTURE) */
+       FRAME_READY,            /* Ready to start grabbing */
+       FRAME_GRABBING,         /* In the process of being grabbed into */
+       FRAME_DONE,             /* Finished grabbing, but not been synced yet */
+       FRAME_ERROR,            /* Something bad happened while processing */
+};
+
+enum {
+       BUFFER_UNUSED,
+       BUFFER_READY,
+       BUFFER_BUSY,
+       BUFFER_DONE,
+};
+
+/* raw camera data <- sbuf (urb transfer buf) */
+struct stv680_scratch {
+       unsigned char *data;
+       volatile int state;
+       int offset;
+       int length;
+};
+
+/* processed data for display ends up here, after bayer */
+struct stv680_frame {
+       unsigned char *data;    /* Frame buffer */
+       volatile int grabstate; /* State of grabbing */
+       unsigned char *curline;
+       int curlinepix;
+       int curpix;
+};
+
+/* this is almost the video structure uvd_t, with extra parameters for stv */
+struct usb_stv {
+       struct video_device vdev;
+
+       struct usb_device *udev;
+
+       unsigned char bulk_in_endpointAddr;     /* __u8  the address of the bulk in endpoint */
+       char *camera_name;
+
+       unsigned int VideoMode; /* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */
+       int SupportedModes;
+       int CIF;
+       int VGA;
+       int QVGA;
+       int cwidth;             /* camera width */
+       int cheight;            /* camera height */
+       int maxwidth;           /* max video width */
+       int maxheight;          /* max video height */
+       int vwidth;             /* current width for video window */
+       int vheight;            /* current height for video window */
+       unsigned long int rawbufsize;
+       unsigned long int maxframesize; /* rawbufsize * 3 for RGB */
+
+       int origGain;
+       int origMode;           /* original camera mode */
+
+       struct semaphore lock;  /* to lock the structure */
+       int user;               /* user count for exclusive use */
+       int removed;            /* device disconnected */
+       int streaming;          /* Are we streaming video? */
+       char *fbuf;             /* Videodev buffer area */
+       urb_t *urb[STV680_NUMSBUF];     /* # of queued bulk transfers */
+       int curframe;           /* Current receiving frame */
+       struct stv680_frame frame[STV680_NUMFRAMES];    /* # frames supported by v4l part */
+       int readcount;
+       int framecount;
+       int error;
+       int dropped;
+       int scratch_next;
+       int scratch_use;
+       int scratch_overflow;
+       struct stv680_scratch scratch[STV680_NUMSCRATCH];       /* for decoders */
+       struct stv680_sbuf sbuf[STV680_NUMSBUF];
+
+       unsigned int brightness;
+       unsigned int chgbright;
+       unsigned int whiteness;
+       unsigned int colour;
+       unsigned int contrast;
+       unsigned int hue;
+       unsigned int palette;
+       unsigned int depth;     /* rgb24 in bits */
+
+       wait_queue_head_t wq;   /* Processes waiting */
+
+       struct proc_dir_entry *proc_entry;      /* /proc/stv680/videoX */
+       int nullpackets;
+};
+
+unsigned char red[256] = {
+       0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+       21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
+       50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
+       79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
+       98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
+       114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
+       127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+       139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
+       150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
+       160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
+       169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
+       177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
+       186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
+       193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
+       201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
+       208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
+       214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
+       221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+       227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
+       233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+       239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
+       245, 245, 246, 246
+};
+
+unsigned char green[256] = {
+       0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+       24, 24, 24, 24, 24, 24, 24, 32, 39, 45, 50, 54,
+       58, 62, 65, 69, 71, 74, 77, 79, 83, 85, 87, 90,
+       92, 93, 95, 98, 100, 101, 104, 106, 107, 109, 111, 113,
+       114, 116, 118, 119, 121, 122, 124, 126, 127, 128, 129, 132,
+       133, 134, 135, 136, 138, 140, 141, 142, 143, 145, 146, 147,
+       148, 149, 150, 152, 153, 154, 155, 156, 157, 159, 160, 161,
+       162, 163, 164, 166, 167, 168, 168, 169, 170, 171, 173, 174,
+       175, 176, 176, 177, 179, 180, 181, 182, 182, 183, 184, 186,
+       187, 187, 188, 189, 190, 191, 191, 193, 194, 195, 195, 196,
+       197, 198, 198, 200, 201, 201, 202, 203, 204, 204, 205, 207,
+       207, 208, 209, 209, 210, 211, 212, 212, 214, 215, 215, 216,
+       217, 217, 218, 218, 219, 221, 221, 222, 223, 223, 224, 225,
+       225, 226, 226, 228, 229, 229, 230, 231, 231, 232, 232, 233,
+       235, 235, 236, 236, 237, 238, 238, 239, 239, 241, 241, 242,
+       243, 243, 244, 244, 245, 245, 246, 248, 248, 249, 249, 250,
+       250, 251, 251, 252, 253, 253, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255
+};
+
+unsigned char blue[256] = {
+       0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+       31, 31, 31, 31, 31, 31, 31, 41, 50, 57, 63, 69,
+       74, 78, 82, 87, 90, 94, 97, 100, 105, 108, 111, 113,
+       116, 118, 121, 124, 127, 128, 131, 134, 136, 139, 140, 143,
+       145, 148, 149, 150, 153, 155, 156, 159, 161, 162, 164, 167,
+       168, 170, 171, 173, 174, 177, 179, 180, 182, 183, 185, 186,
+       187, 189, 190, 192, 193, 195, 196, 198, 199, 201, 202, 204,
+       205, 207, 208, 210, 211, 213, 213, 214, 216, 217, 219, 220,
+       222, 223, 223, 224, 226, 227, 229, 230, 230, 232, 233, 235,
+       236, 236, 238, 239, 241, 242, 242, 244, 245, 247, 247, 248,
+       250, 251, 251, 253, 254, 254, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+       255, 255, 255, 255
+};
diff --git a/drivers/usb/vicam.c b/drivers/usb/vicam.c
new file mode 100644 (file)
index 0000000..9a6787d
--- /dev/null
@@ -0,0 +1,986 @@
+/* -*- linux-c -*-
+ * USB ViCAM driver
+ *
+ * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
+ * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
+ *
+ *      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 driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
+ *
+ * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
+ *
+ * TODO:
+ *     - find out the ids for the Vista Imaging ViCAM
+ *
+ * History:
+ *
+ * 2001_07_07 - 0.1 - christopher: first version
+ * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try 
+                       while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
+                     yep, moving pictures.
+ * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
+                       get gqcam-0.9, compile it and run. Better than dd ;-).
+ * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
+                       kill update_params if it does not seem to work for you.
+ * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
+
+ *
+ * FIXME: It crashes on rmmod with camera plugged.
+ */
+#define DEBUG 1
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
+
+#include <asm/io.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
+#include <linux/videodev.h>
+
+#include "vicam.h"
+#include "vicamurbs.h"
+
+/* Version Information */
+#define DRIVER_VERSION "v0"
+#define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
+#define DRIVER_DESC "USB ViCAM Driver"
+
+/* Define these values to match your device */
+#define USB_VICAM_VENDOR_ID    0x04C1
+#define USB_VICAM_PRODUCT_ID   0x009D
+
+/* table of devices that work with this driver */
+static struct usb_device_id vicam_table [] = {
+       { USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
+       { }                                     /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, vicam_table);
+
+static int video_nr = -1;              /* next avail video device */
+static struct usb_driver vicam_driver;
+
+static char *buf, *buf2;
+static int change_pending = 0; 
+
+static int vicam_parameters(struct usb_vicam *vicam);
+
+/******************************************************************************
+ *
+ *  Memory management functions
+ *
+ *  Taken from bttv-drivers.c 2.4.7-pre3
+ *
+ ******************************************************************************/
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ *    out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed.  We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+       unsigned long ret = 0UL;
+       pmd_t *pmd;
+       pte_t *ptep, pte;
+
+       if (!pgd_none(*pgd)) {
+               pmd = pmd_offset(pgd, adr);
+               if (!pmd_none(*pmd)) {
+                       ptep = pte_offset(pmd, adr);
+                       pte = *ptep;
+                       if(pte_present(pte)) {
+                               ret  = (unsigned long) page_address(pte_page(pte));
+                               ret |= (adr & (PAGE_SIZE - 1));
+
+                       }
+               }
+       }
+       return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+       unsigned long kva, ret;
+
+       kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+       ret = virt_to_bus((void *)kva);
+       return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+       unsigned long va, kva, ret;
+
+       va = VMALLOC_VMADDR(adr);
+       kva = uvirt_to_kva(pgd_offset_k(va), va);
+       ret = virt_to_bus((void *)kva);
+       return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+       unsigned long va, kva, ret;
+
+       va = VMALLOC_VMADDR(adr);
+       kva = uvirt_to_kva(pgd_offset_k(va), va);
+       ret = __pa(kva);
+       return ret;
+}
+
+static void * rvmalloc(signed long size)
+{
+       void * mem;
+       unsigned long adr, page;
+
+       mem=vmalloc_32(size);
+       if (mem)
+       {
+               memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+               adr=(unsigned long) mem;
+               while (size > 0)
+               {
+                       page = kvirt_to_pa(adr);
+                       mem_map_reserve(virt_to_page(__va(page)));
+                       adr+=PAGE_SIZE;
+                       size-=PAGE_SIZE;
+               }
+       }
+       return mem;
+}
+
+static void rvfree(void * mem, signed long size)
+{
+       unsigned long adr, page;
+
+       if (mem)
+       {
+               adr=(unsigned long) mem;
+               while (size > 0)
+               {
+                       page = kvirt_to_pa(adr);
+                       mem_map_unreserve(virt_to_page(__va(page)));
+                       adr+=PAGE_SIZE;
+                       size-=PAGE_SIZE;
+               }
+               vfree(mem);
+       }
+}
+
+/******************************************************************************
+ *
+ *  Foo Bar
+ *
+ ******************************************************************************/
+
+/**
+ *     usb_vicam_debug_data
+ */
+static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
+{
+       int i;
+
+       if (!debug)
+               return;
+
+       printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
+               function, size);
+       for (i = 0; i < size; ++i) {
+               printk ("%.2x ", data[i]);
+       }
+       printk ("\n");
+}
+
+/*****************************************************************************
+ *
+ *  Send command to vicam
+ *
+ *****************************************************************************/
+
+static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
+       unsigned short value, unsigned char *cp, int size)
+{
+       int ret;
+       unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
+
+       /* Needs to return data I think, works for sending though */
+       memcpy(transfer_buffer, cp, size);
+       
+       ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
+
+       kfree(transfer_buffer);
+       if (ret)
+               printk("vicam: error: %d\n", ret);
+       mdelay(100);
+       return ret;
+}
+
+
+/*****************************************************************************
+ *
+ *  Video4Linux Helpers
+ * 
+ *****************************************************************************/
+
+static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
+{
+       dbg("vicam_get_capability");
+
+       strcpy(b->name, vicam->camera_name);
+       b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
+       b->channels = 1;
+       b->audios = 0;
+
+       b->maxwidth = vicam->width[vicam->sizes-1];
+       b->maxheight = vicam->height[vicam->sizes-1];
+       b->minwidth = vicam->width[0];
+       b->minheight = vicam->height[0];
+
+       return 0;
+}
+               
+static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+       dbg("vicam_get_channel");
+
+       if (v->channel != 0)
+               return -EINVAL;
+       v->flags = 0;
+       v->tuners = 0;
+       v->type = VIDEO_TYPE_CAMERA;
+       strcpy(v->name, "Camera");
+
+       return 0;
+} 
+               
+static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+       dbg("vicam_set_channel");
+
+       if (v->channel != 0)
+               return -EINVAL;
+       
+       return 0;
+}
+               
+static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
+{
+       int i;
+
+       dbg("vicam_get_mmapbuffer");
+
+       memset(vm, 0, sizeof(vm));
+       vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
+       vm->frames = VICAM_NUMFRAMES;
+
+       for (i=0; i<VICAM_NUMFRAMES; i++)
+               vm->offsets[i] = vicam->maxframesize * i;
+
+       return 0;
+}
+
+static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+       dbg("vicam_get_picture");
+
+       /* This is probably where that weird 0x56 call goes */
+       p->brightness = vicam->win.brightness;
+       p->hue = vicam->win.hue;
+       p->colour = vicam->win.colour;
+       p->contrast = vicam->win.contrast;
+       p->whiteness = vicam->win.whiteness;
+       p->depth = vicam->win.depth;
+       p->palette = vicam->win.palette;
+
+       return 0;
+}
+
+static void synchronize(struct usb_vicam *vicam)
+{
+       change_pending = 1;
+       interruptible_sleep_on(&vicam->wait);
+       vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+       mdelay(10);
+       vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+       mdelay(10);
+}
+
+static void params_changed(struct usb_vicam *vicam)
+{
+#if 1
+       synchronize(vicam);
+       mdelay(10);
+       vicam_parameters(vicam);
+       printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+#endif
+}
+
+static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+       int changed = 0;
+       info("vicam_set_picture (%d)", p->brightness);
+
+
+#define SET(x) \
+       if (vicam->win.x != p->x) \
+               vicam->win.x = p->x, changed = 1;
+       SET(brightness);
+       SET(hue);
+       SET(colour);
+       SET(contrast);
+       SET(whiteness);
+       SET(depth);
+       SET(palette);
+       if (changed)
+               params_changed(vicam);
+
+       return 0;
+       /* Investigate what should be done maybe 0x56 type call */
+       if (p->depth != 8) return 1;
+       if (p->palette != VIDEO_PALETTE_GREY) return 1;
+
+       return 0;
+}
+
+/* FIXME - vicam_sync_frame - important */
+static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
+{
+       dbg("vicam_sync_frame");
+
+       if(frame <0 || frame >= VICAM_NUMFRAMES)
+               return -EINVAL;
+
+       /* Probably need to handle various cases */
+/*     ret=vicam_newframe(vicam, frame);
+       vicam->frame[frame].grabstate=FRAME_UNUSED;
+*/
+       return 0;
+}
+       
+static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+       dbg("vicam_get_window");
+
+       vw->x = 0;
+       vw->y = 0;
+       vw->chromakey = 0;
+       vw->flags = 0;
+       vw->clipcount = 0;
+       vw->width = vicam->win.width;
+       vw->height = vicam->win.height;
+
+       return 0;
+}
+
+static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+       info("vicam_set_window");
+               
+       if (vw->flags)
+               return -EINVAL;
+       if (vw->clipcount)
+               return -EINVAL;
+
+       if (vicam->win.width == vw->width && vicam->win.height == vw->height)
+               return 0;
+
+       /* Pick largest mode that is smaller than specified res */
+       /* If specified res is too small reject                 */
+
+       /* Add urb send to device... */
+
+       vicam->win.width = vw->width;
+       vicam->win.height = vw->height;
+       params_changed(vicam);
+
+       return 0;
+}
+
+/* FIXME - vicam_mmap_capture - important */
+static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
+{
+       dbg("vicam_mmap_capture");
+
+       /* usbvideo.c looks good for using here */
+
+       /* 
+       if (vm->frame >= VICAM_NUMFRAMES)
+               return -EINVAL;
+       if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
+               return -EBUSY;
+       vicam->frame[vm->frame].grabstate=FRAME_READY;
+       */
+
+       /* No need to vicam_set_window here according to Alan */
+
+       /*
+       if (!vicam->streaming)
+               vicam_start_stream(vicam);
+       */
+
+       /* set frame as ready */
+
+       return 0;
+}
+
+/*****************************************************************************
+ *
+ *  Video4Linux
+ * 
+ *****************************************************************************/
+
+static int vicam_v4l_open(struct video_device *vdev, int flags)
+{
+       struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+       int err = 0;
+       
+       dbg("vicam_v4l_open");
+
+       MOD_INC_USE_COUNT; 
+       down(&vicam->sem);
+
+       if (vicam->open_count)          /* Maybe not needed? */
+               err = -EBUSY;
+       else {
+               vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
+               if (!vicam->fbuf)
+                       err=-ENOMEM;
+               else {
+                       vicam->open_count = 1;
+               }
+#ifdef BLINKING
+               vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+               info ("led on");
+               vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+#endif
+       }
+
+       up(&vicam->sem);
+       if (err)
+               MOD_DEC_USE_COUNT;
+       return err;
+}
+
+static void vicam_v4l_close(struct video_device *vdev)
+{
+       struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+       dbg("vicam_v4l_close");
+       
+       down(&vicam->sem);
+
+#ifdef BLINKING
+       info ("led off");
+       vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+//     vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
+#endif
+
+       rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
+       vicam->fbuf = 0;
+       vicam->open_count=0;
+
+       up(&vicam->sem);
+       /* Why does se401.c have a usbdevice check here? */
+       /* If device is unplugged while open, I guess we only may unregister now */
+       MOD_DEC_USE_COUNT;
+}
+
+static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock)
+{
+       //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+       dbg("vicam_v4l_read(%ld)", buflen);
+
+       if (!vdev || !buf)
+               return -EFAULT;
+
+       if (copy_to_user(user_buf, buf2, buflen))
+               return -EFAULT;
+       return buflen;
+}
+
+static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+       info("vicam_v4l_write");
+       return -EINVAL;
+}
+
+static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+       struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+       int ret = -EL3RST;
+
+       if (!vicam->udev)
+               return -EIO;
+
+       down(&vicam->sem);
+
+       switch (cmd) {
+       case VIDIOCGCAP:
+       {
+               struct video_capability b;
+               ret = vicam_get_capability(vicam,&b);
+               dbg("name %s",b.name);
+               if (copy_to_user(arg, &b, sizeof(b)))
+                       ret = -EFAULT;
+       }
+       case VIDIOCGFBUF:
+       {
+               struct video_buffer vb;
+               info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
+               /* frame buffer not supported, not used */
+               memset(&vb, 0, sizeof(vb));
+               vb.base = NULL;
+               
+               /* FIXME - VIDIOCGFBUF - why the void */
+               if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
+                       ret = -EFAULT;
+               ret = 0;
+       }
+       case VIDIOCGWIN:
+       {
+               struct video_window vw;
+               ret = vicam_get_window(vicam, &vw);
+               if (copy_to_user(arg, &vw, sizeof(vw)))
+                       ret = -EFAULT;
+       }
+       case VIDIOCSWIN:
+       {
+               struct video_window vw;
+               if (copy_from_user(&vw, arg, sizeof(vw)))
+                       ret = -EFAULT;
+               else
+                       ret = vicam_set_window(vicam, &vw);
+               return ret;
+       }
+       case VIDIOCGCHAN:
+       {
+               struct video_channel v;
+
+               if (copy_from_user(&v, arg, sizeof(v)))
+                       ret = -EFAULT;
+               else {
+                       ret = vicam_get_channel(vicam,&v);
+                       if (copy_to_user(arg, &v, sizeof(v)))
+                               ret = -EFAULT;
+               }
+       }
+       case VIDIOCSCHAN:
+       {
+               struct video_channel v;
+               if (copy_from_user(&v, arg, sizeof(v)))
+                       ret = -EFAULT;
+               else
+                       ret = vicam_set_channel(vicam,&v);
+       }
+       case VIDIOCGPICT:
+       {
+               struct video_picture p;
+               ret = vicam_get_picture(vicam, &p);
+               if (copy_to_user(arg, &p, sizeof(p)))
+                       ret = -EFAULT;
+       }
+       case VIDIOCSPICT:
+       {
+               struct video_picture p;
+               if (copy_from_user(&p, arg, sizeof(p)))
+                       ret = -EFAULT;
+               else
+                       ret = vicam_set_picture(vicam, &p);
+       }
+       case VIDIOCGMBUF:
+       {
+               struct video_mbuf vm;
+               ret = vicam_get_mmapbuffer(vicam,&vm);
+               /* FIXME - VIDIOCGMBUF - why the void */
+               if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+                       ret = -EFAULT;
+       }
+       case VIDIOCMCAPTURE:
+       {
+               struct video_mmap vm;
+               ret = vicam_mmap_capture(vicam, &vm);
+               /* FIXME: This is probably not right */
+       }
+       case VIDIOCSYNC:
+       {
+               int frame;
+               /* FIXME - VIDIOCSYNC - why the void */
+               if (copy_from_user((void *)&frame, arg, sizeof(int)))
+                       ret = -EFAULT;
+               else
+                       ret = vicam_sync_frame(vicam,frame);
+       }
+
+       case VIDIOCKEY:
+               ret = 0;
+       case VIDIOCCAPTURE:
+       case VIDIOCSFBUF:
+       case VIDIOCGTUNER:
+       case VIDIOCSTUNER:
+       case VIDIOCGFREQ:
+       case VIDIOCSFREQ:
+       case VIDIOCGAUDIO:
+       case VIDIOCSAUDIO:
+       case VIDIOCGUNIT:
+               ret = -EINVAL;
+
+       default:
+       {
+               info("vicam_v4l_ioctl - %ui",cmd);
+               ret = -ENOIOCTLCMD;
+       }
+       } /* end switch */
+
+       up(&vicam->sem);
+        return ret;
+}
+
+static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size)
+{
+       struct usb_vicam *vicam = (struct usb_vicam *)dev;
+       unsigned long start = (unsigned long)adr;
+       unsigned long page, pos;
+
+       down(&vicam->sem);
+       
+       if (vicam->udev == NULL) {
+               up(&vicam->sem);
+               return -EIO;
+       }
+#if 0
+       if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+               up(&vicam->sem);
+               return -EINVAL;
+       }
+#endif
+       pos = (unsigned long)vicam->fbuf;
+       while (size > 0) {
+               page = kvirt_to_pa(pos);
+               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
+                       up(&vicam->sem);
+                       return -EAGAIN;
+               }
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+       up(&vicam->sem);
+
+        return 0;
+}
+
+/* FIXME - vicam_v4l_init */
+static int vicam_v4l_init(struct video_device *dev)
+{
+       /* stick proc fs stuff in here if wanted */
+       dbg("vicam_v4l_init");
+       return 0;
+}
+
+/* FIXME - vicam_template - important */
+static struct video_device vicam_template = {
+       name:           "vicam USB camera",
+       type:           VID_TYPE_CAPTURE,
+       hardware:       VID_HARDWARE_SE401, /* need to ask for own id */
+       open:           vicam_v4l_open,
+       close:          vicam_v4l_close,
+       read:           vicam_v4l_read,
+       write:          vicam_v4l_write,
+       ioctl:          vicam_v4l_ioctl,
+       mmap:           vicam_v4l_mmap,
+       initialize:     vicam_v4l_init,
+};
+
+/******************************************************************************
+ *
+ *  Some Routines
+ *
+ ******************************************************************************/
+
+/*
+Flash the led
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+info ("led on");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+info ("led off");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+*/
+
+static void vicam_bulk(struct urb *urb)
+{
+       struct usb_vicam *vicam = urb->context;
+
+       /*      if (!vicam || !vicam->dev || !vicam->used)
+               return;
+       */
+
+       if (urb->status)
+               printk("vicam%d: nonzero read/write bulk status received: %d",
+                       0, urb->status);
+
+       urb->actual_length = 0;
+       urb->dev = vicam->udev;
+
+       memcpy(buf2, buf+64, 0x1e480);
+       if (vicam->fbuf)
+               memcpy(vicam->fbuf, buf+64, 0x1e480);
+
+       if (!change_pending) {
+               if (usb_submit_urb(urb))
+                       dbg("failed resubmitting read urb");
+       } else {
+               change_pending = 0;
+               wake_up_interruptible(&vicam->wait);
+       }
+}
+
+static int vicam_parameters(struct usb_vicam *vicam)
+{
+       unsigned char req[0x10];
+       unsigned int shutter;
+       shutter = 10;
+
+       switch (vicam->win.width) {
+       case 512:
+       default:
+               memcpy(req, s512x242bw, 0x10);
+               break;
+       case 256:
+               memcpy(req, s256x242bw, 0x10);
+               break;
+       case 128:
+               memcpy(req, s128x122bw, 0x10);
+               break;
+       }
+
+
+       mdelay(10);
+       vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+       info ("led on");
+       vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+
+       mdelay(10);
+
+       shutter = vicam->win.contrast / 256;
+       if (shutter == 0)
+               shutter = 1;
+       printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );
+       req[0] = vicam->win.brightness /256;
+       shutter = 15600/shutter - 1;
+       req[6] = shutter & 0xff;
+       req[7] = (shutter >> 8) & 0xff;
+       vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
+       mdelay(10);
+       vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
+       mdelay(10);
+
+       return 0;
+}
+
+static int vicam_init(struct usb_vicam *vicam)
+{
+       int width[] = {128, 256, 512};
+       int height[] = {122, 242, 242};
+
+       dbg("vicam_init");
+       buf = kmalloc(0x1e480, GFP_KERNEL);
+       buf2 = kmalloc(0x1e480, GFP_KERNEL);
+       if ((!buf) || (!buf2)) {
+               printk("Not enough memory for vicam!\n");
+               goto error;
+       }
+
+       /* do we do aspect correction in kernel or not? */
+       vicam->sizes = 3;
+       vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+       vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+       memcpy(vicam->width, &width, sizeof(width));
+       memcpy(vicam->height, &height, sizeof(height));
+       vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
+
+       /* Download firmware to camera */
+       vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
+       vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
+       vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+       vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
+       vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
+       vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+
+       vicam_parameters(vicam);
+
+       FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
+                     buf, 0x1e480, vicam_bulk, vicam);
+       printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+
+       return 0;
+error:
+       if (buf)
+               kfree(buf);
+       if (buf2)
+               kfree(buf2);
+       return 1;
+}
+
+static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
+       const struct usb_device_id *id)
+{
+       struct usb_vicam *vicam;
+       char *camera_name=NULL;
+
+       dbg("vicam_probe");
+
+       /* See if the device offered us matches what we can accept */
+       if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
+           (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
+               return NULL;
+       }
+       
+       camera_name="3Com HomeConnect USB";
+       info("ViCAM camera found: %s", camera_name);
+       
+       vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
+       if (vicam == NULL) {
+               err ("couldn't kmalloc vicam struct");
+               return NULL;
+       }
+       memset(vicam, 0, sizeof(*vicam));
+       
+       vicam->udev = udev;
+       vicam->camera_name = camera_name;
+       vicam->win.brightness = 128;
+       vicam->win.contrast = 10;
+
+       /* FIXME */
+       if (vicam_init(vicam))
+               return NULL;
+       memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
+       memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
+       
+       if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+               err("video_register_device");
+               return NULL;
+       }
+
+       info("registered new video device: video%d", vicam->vdev.minor);
+       
+       init_MUTEX (&vicam->sem);
+       init_waitqueue_head(&vicam->wait);
+       
+       return vicam;
+}
+
+
+/* FIXME - vicam_disconnect - important */
+static void vicam_disconnect(struct usb_device *udev, void *ptr)
+{
+       struct usb_vicam *vicam;
+
+       vicam = (struct usb_vicam *) ptr;
+
+       if (!vicam->open_count)
+               video_unregister_device(&vicam->vdev);
+       vicam->udev = NULL;
+/*
+       vicam->frame[0].grabstate = FRAME_ERROR;
+       vicam->frame[1].grabstate = FRAME_ERROR;
+*/
+
+       /* Free buffers and shit */
+
+       info("%s disconnected", vicam->camera_name);
+       synchronize(vicam);
+
+       if (!vicam->open_count) {
+               /* Other random junk */
+               kfree(vicam);
+               vicam = NULL;
+       }
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vicam_driver = {
+       name:           "vicam",
+       probe:          vicam_probe,
+       disconnect:     vicam_disconnect,
+       id_table:       vicam_table,
+};
+
+/******************************************************************************
+ *
+ *  Module Routines
+ *
+ ******************************************************************************/
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module paramaters */
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+static int __init usb_vicam_init(void)
+{
+       int result;
+
+       printk("VICAM: initializing\n");
+       /* register this driver with the USB subsystem */
+       result = usb_register(&vicam_driver);
+       if (result < 0) {
+               err("usb_register failed for the "__FILE__" driver. Error number %d",
+                   result);
+               return -1;
+       }
+
+       info(DRIVER_VERSION " " DRIVER_AUTHOR);
+       info(DRIVER_DESC);
+       return 0;
+}
+
+static void __exit usb_vicam_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&vicam_driver);
+}
+
+module_init(usb_vicam_init);
+module_exit(usb_vicam_exit);
diff --git a/drivers/usb/vicam.h b/drivers/usb/vicam.h
new file mode 100644 (file)
index 0000000..46b4aad
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ * 
+ */
+
+#ifndef __LINUX_VICAM_H
+#define __LINUX_VICAM_H
+
+
+#ifdef CONFIG_USB_DEBUG
+       static int debug = 1;
+#else
+       static int debug;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+
+#define VICAM_NUMFRAMES 30
+#define VICAM_NUMSBUF 1
+
+/* USB REQUEST NUMBERS */
+#define VICAM_REQ_VENDOR       0xff
+#define VICAM_REQ_CAMERA_POWER 0x50
+#define VICAM_REQ_CAPTURE      0x51
+#define VICAM_REQ_LED_CONTROL  0x55
+#define VICAM_REQ_GET_SOMETHIN 0x56
+/* not required but lets you know camera is on */
+/* camera must be on to turn on led */
+/* 0x01 always on  0x03 on when picture taken (flashes) */
+
+struct picture_parm
+{
+       int width;
+       int height;
+       int brightness;
+       int hue;
+       int colour;
+       int contrast;
+       int whiteness;
+       int depth;
+       int palette;
+};
+
+struct vicam_scratch {
+        unsigned char *data;
+        volatile int state;
+        int offset;
+        int length;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct usb_vicam
+{
+       struct video_device vdev;
+       struct usb_device *udev;
+
+       int open_count; /* number of times this port has been opened */
+       struct semaphore sem;                   /* locks this structure */
+       wait_queue_head_t wait;                 /* Processes waiting */ 
+
+       int streaming;
+
+       /* v4l stuff */
+       char *camera_name;
+       char *fbuf;
+       urb_t *urb[VICAM_NUMSBUF];
+       int sizes;
+       int *width;
+       int *height;
+       int maxframesize;
+       struct picture_parm win;
+       struct proc_dir_entry *proc_entry;      /* /proc/se401/videoX */
+       struct urb readurb;
+};
+
+#endif
diff --git a/drivers/usb/vicamurbs.h b/drivers/usb/vicamurbs.h
new file mode 100644 (file)
index 0000000..e19efbc
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ * 
+ */
+
+
+#ifndef __LINUX_VICAMURBS_H
+#define __LINUX_VICAMURBS_H
+
+/* -------------------------------------------------------------------------- */
+
+/* FIXME - Figure out transfers so that this doesn't need to be here
+ *
+ * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */
+
+/* Request 0x51 Image Setup */
+
+/* 128x98 ? 0x3180 size */
+static unsigned char s128x98bw[] = {
+  0,    0x34, 0xC4, 0x00, 0x00, 0x00, 0,    0,
+  0x18, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 128x122 3D80 size */
+static unsigned char s128x122bw[] = {
+  0,    0x34, 0xF4, 0x00, 0x00, 0x00, 0,    0,
+  0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 256x242 ? 0xF280 size */
+static unsigned char s256x242bw[] = {
+  0,    0x03, 0xC8, 0x03, 0x00, 0x00, 0,    0,
+  0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 512x242 0x1E480 size */
+static unsigned char s512x242bw[] = {
+  0,    0x05, 0x90, 0x07, 0x00, 0x00, 0,    0,
+  0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* In s512x242:
+   byte 0: gain -- higher number means brighter image
+   byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000).
+*/
+
+/* -------------------------------------------------------------------------- */
+
+static unsigned char fsetup[] = {
+  0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64,
+
+  0x00, 0x00
+};
+
+static unsigned char firmware1[] = {
+  0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64,
+
+  0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09,
+  0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03,
+  0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07,
+  0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
+};
+
+static unsigned char findex1[] = {
+  0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64,
+
+  0x18, 0x00, 0x00, 0x00
+};
+
+static unsigned char firmware2[] = {
+  0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64,
+
+  0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07,
+  0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01,
+  0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00,
+  0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07,
+  0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00,
+  0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0,
+  0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07,
+  0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00,
+  0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0,
+  0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87,
+  0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09,
+  0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0,
+  0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01,
+  0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07,
+  0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0,
+  0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00,
+  0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77,
+  0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57,
+  0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57,
+  0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF,
+  0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05,
+  0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF,
+  0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00,
+  0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01,
+  0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09,
+  0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06,
+  0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0,
+  0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09,
+  0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06,
+  0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06,
+  0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00,
+  0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF,
+  0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07,
+  0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05,
+  0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17,
+  0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06,
+  0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00,
+  0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57,
+  0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03,
+  0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF,
+  0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07,
+  0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00,
+  0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00,
+  0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02,
+  0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57,
+  0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00,
+  0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02,
+  0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90,
+  0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B,
+  0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF,
+  0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07,
+  0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF,
+  0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E,
+  0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00,
+  0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67,
+  0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD,
+  0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0,
+  0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF,
+  0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0,
+  0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00,
+  0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0,
+  0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00,
+  0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00,
+  0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+  0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02,
+  0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0,
+  0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+  0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1,
+  0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF,
+  0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF,
+  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07,
+  0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF,
+  0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06,
+  0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67,
+  0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00,
+  0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0,
+  0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF,
+  0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+  0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02,
+  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+  0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C,
+  0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00,
+  0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+  0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02,
+  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+  0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF,
+  0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF,
+  0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B,
+  0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+  0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF,
+  0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00,
+  0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06,
+  0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02,
+  0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF,
+  0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05,
+  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07,
+  0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06,
+  0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01,
+  0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07,
+  0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07,
+  0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01,
+  0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0,
+  0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06,
+  0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06,
+  0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06,
+  0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00,
+  0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05,
+  0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+  0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA,
+  0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1,
+  0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00,
+  0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00,
+  0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF,
+  0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57,
+  0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07,
+  0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
+  0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
+  0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
+  0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67,
+  0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0,
+  0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00,
+  0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00,
+  0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00,
+  0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05,
+  0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8,
+  0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05,
+  0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07,
+  0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05,
+  0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B,
+  0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17,
+  0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07,
+  0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09,
+  0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00,
+  0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05,
+  0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07,
+  0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9,
+  0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00,
+  0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0,
+  0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67,
+  0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA,
+  0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0,
+  0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87,
+  0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF,
+  0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0,
+  0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF,
+  0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0,
+  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+  0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+  0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05,
+  0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67,
+  0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+  0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07,
+  0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67,
+  0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0,
+  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA,
+  0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+  0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
+  0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1,
+  0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF,
+  0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77,
+  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+  0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77,
+  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+  0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80,
+  0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char findex2[] = {
+  0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64,
+
+  0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00,
+  0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00,
+  0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00,
+  0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00,
+  0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00,
+  0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00,
+  0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01,
+  0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01,
+  0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01,
+  0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01,
+  0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01,
+  0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01,
+  0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01,
+  0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01,
+  0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02,
+  0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02,
+  0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02,
+  0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02,
+  0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02,
+  0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02,
+  0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02,
+  0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02,
+  0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03,
+  0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03,
+  0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03,
+  0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03,
+  0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03,
+  0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03,
+  0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03,
+  0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04,
+  0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04,
+  0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04,
+  0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04,
+  0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04,
+  0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04,
+  0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04,
+  0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04,
+  0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
+};
+
+#endif
index 5e2957c7f8e55ae87a44166c9165973db674eae6..b3b4a09d4972a1f20390a741f549b41271156bc0 100644 (file)
@@ -271,10 +271,10 @@ int PROC_CONSOLE(const struct fb_info *info)
                 /* XXX Should report error here? */
                 return fgc;
 
-        if (MINOR(current->tty->device) < 1)
+        if (minor(current->tty->device) < 1)
                 return fgc;
 
-        return MINOR(current->tty->device) - 1;
+        return minor(current->tty->device) - 1;
 }
 
 
index b04a2879c37c9ef9f4a4dbb7b25ba742e82a0e5f..9c586f2866326d7839c6287cc506c481ce942164 100644 (file)
@@ -625,7 +625,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
 #if 1 /* to go away in 2.5.0 */
 int GET_FB_IDX(kdev_t rdev)
 {
-    int fbidx = MINOR(rdev);
+    int fbidx = minor(rdev);
     if (fbidx >= 32) {
        int newfbidx = fbidx >> 5;
        static int warned;
@@ -719,7 +719,7 @@ register_framebuffer(struct fb_info *fb_info)
        for (i = 0 ; i < FB_MAX; i++)
                if (!registered_fb[i])
                        break;
-       fb_info->node = MKDEV(FB_MAJOR, i);
+       fb_info->node = mk_kdev(FB_MAJOR, i);
        registered_fb[i] = fb_info;
        if (!fb_ever_opened[i]) {
                struct module *owner = fb_info->fbops->owner;
index 62897efab91e2ca5fcd0bc0e4367b1c5d5027317..1868b6f2125723d40323cca446759452756c84ca 100644 (file)
@@ -648,7 +648,7 @@ int __init vesafb_init(void)
        
        strcpy(fb_info.modename, "VESA VGA");
        fb_info.changevar = NULL;
-       fb_info.node = -1;
+       fb_info.node = NODEV;
        fb_info.fbops = &vesafb_ops;
        fb_info.disp=&disp;
        fb_info.switch_con=&vesafb_switch;
index 9a7b210cdb9cf649328c171020da5305c84e6c19..c133fa3c68d77b784ddb9418697bfc90f5b2b97a 100644 (file)
@@ -262,7 +262,7 @@ affs_read_super(struct super_block *sb, void *data, int silent)
         * blocks, we will have to change it.
         */
 
-       blocks = blk_size[MAJOR(dev)] ? blk_size[MAJOR(dev)][MINOR(dev)] : 0;
+       blocks = blk_size[major(dev)] ? blk_size[major(dev)][minor(dev)] : 0;
        if (!blocks) {
                printk(KERN_ERR "AFFS: Could not determine device size\n");
                goto out_error;
index c8625a66badb19d2059c42a8869f097c38f61564..8dc002027c49987ffd4b7dafc08ee8786d09dc8b 100644 (file)
@@ -70,7 +70,7 @@ static int get_device_index(struct coda_mount_data *data)
                inode = file->f_dentry->d_inode;
        
        if(!inode || !S_ISCHR(inode->i_mode) ||
-          MAJOR(inode->i_rdev) != CODA_PSDEV_MAJOR) {
+          major(inode->i_rdev) != CODA_PSDEV_MAJOR) {
                if(file)
                        fput(file);
 
@@ -78,7 +78,7 @@ static int get_device_index(struct coda_mount_data *data)
                return -1;
        }
 
-       idx = MINOR(inode->i_rdev);
+       idx = minor(inode->i_rdev);
        fput(file);
 
        if(idx < 0 || idx >= MAX_CODADEVS) {
index 895970b77a185c86ff387eaef3911c67888ff6c6..2132104cddb0cd934e80df94575684d0bb525ed8 100644 (file)
@@ -115,7 +115,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
        struct buffer_head * read_array[BLKS_PER_BUF];
        unsigned i, blocknr, buffer, unread;
        unsigned long devsize;
-       int major, minor;
+       unsigned int major, minor;
        
        char *data;
 
@@ -140,8 +140,8 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
        }
 
        devsize = ~0UL;
-       major = MAJOR(sb->s_dev);
-       minor = MINOR(sb->s_dev);
+       major = major(sb->s_dev);
+       minor = minor(sb->s_dev);
 
        if (blk_size[major])
                devsize = blk_size[major][minor] >> 2;
index db6ec7adfd1ad8577963fa333d5738892749cc09..9aa28ef93510666e5924e717990d064909c0196d 100644 (file)
@@ -1063,16 +1063,16 @@ static struct devfs_entry *_devfs_get_root_entry (void)
     if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )
         == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
-    new->u.fcb.u.device.major = MAJOR (devnum);
-    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.u.device.major = major (devnum);
+    new->u.fcb.u.device.minor = minor (devnum);
     new->u.fcb.ops = &devfsd_fops;
     _devfs_append_entry (root_entry, new, FALSE, NULL);
 #ifdef CONFIG_DEVFS_DEBUG
     if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
         == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
-    new->u.fcb.u.device.major = MAJOR (devnum);
-    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.u.device.major = major (devnum);
+    new->u.fcb.u.device.minor = minor (devnum);
     new->u.fcb.ops = &stat_fops;
     _devfs_append_entry (root_entry, new, FALSE, NULL);
 #endif
@@ -1558,8 +1558,8 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
                    name, S_ISCHR (mode) ? "char" : "block");
            return NULL;
        }
-       major = MAJOR (devnum);
-       minor = MINOR (devnum);
+       major = major (devnum);
+       minor = minor (devnum);
     }
     if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
     {
index 39a7d09a254de23dc2b7077633791c97c56e463d..e09c869dfb2c6fb8d1ab6c3d4fd20d4ef93f3a7e 100644 (file)
@@ -320,8 +320,8 @@ void devfs_dealloc_devnum (char type, kdev_t devnum)
        semaphore = &block_semaphore;
        list = &block_list;
     }
-    major = MAJOR (devnum);
-    minor = MINOR (devnum);
+    major = major (devnum);
+    minor = minor (devnum);
     down (semaphore);
     for (entry = list->first; entry != NULL; entry = entry->next)
     {
index a97206d130765617204e8e959dedfe52d1648e43..a9a697a0a08a69af277dbc4b0b8de53d2295b083 100644 (file)
@@ -1483,7 +1483,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
                        goto out;
        }
 
-       ret = -NODEV;
+       ret = -ENODEV;
        if (sb && sb_has_quota_enabled(sb, type))
                ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);
 out:
index 062ed9374aa5a15bded1dae8bc5af7ac6272c98c..59ee8ad176acd1b0aa8940cdf388833c10f684bb 100644 (file)
@@ -189,7 +189,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
        struct ext3_super_block * es;
        int fatal = 0, err;
 
-       if (!inode->i_dev) {
+       if (kdev_none(inode->i_dev)) {
                printk ("ext3_free_inode: inode has no device\n");
                return;
        }
index 5a0282393f779215ff35600d3ed9f77b0cf4677d..6706e7af5e83d73634e2f22cde7068324c493ab0 100644 (file)
@@ -389,8 +389,8 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
        list_for_each(l, &sbi->s_orphan) {
                struct inode *inode = orphan_list_entry(l);
                printk(KERN_ERR "  "
-                      "inode 0x%04x:%ld at %p: mode %o, nlink %d, next %d\n",
-                      inode->i_dev, inode->i_ino, inode,
+                      "inode 0x%04x.0x%04x:%ld at %p: mode %o, nlink %d, next %d\n",
+                      major(inode->i_dev), minor(inode->i_dev), inode->i_ino, inode,
                       inode->i_mode, inode->i_nlink, 
                       le32_to_cpu(NEXT_ORPHAN(inode)));
        }
@@ -430,7 +430,7 @@ void ext3_put_super (struct super_block * sb)
        J_ASSERT(list_empty(&sbi->s_orphan));
 
        invalidate_buffers(sb->s_dev);
-       if (j_dev != sb->s_dev) {
+       if (!kdev_same(j_dev, sb->s_dev)) {
                /*
                 * Invalidate the journal device's buffers.  We don't want them
                 * floating about in memory - the physical journal device may
@@ -917,7 +917,7 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
        sbi->s_resuid = EXT3_DEF_RESUID;
        sbi->s_resgid = EXT3_DEF_RESGID;
        if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
-               sb->s_dev = 0;
+               sb->s_dev = NODEV;
                goto out_fail;
        }
 
@@ -1259,7 +1259,7 @@ static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
 }
 
 static journal_t *ext3_get_dev_journal(struct super_block *sb,
-                                      int dev)
+                                      kdev_t j_dev)
 {
        struct buffer_head * bh;
        journal_t *journal;
@@ -1268,16 +1268,15 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        int hblock, blocksize;
        unsigned long sb_block;
        unsigned long offset;
-       kdev_t journal_dev = to_kdev_t(dev);
        struct ext3_super_block * es;
        struct block_device *bdev;
 
-       bdev = ext3_blkdev_get(journal_dev);
+       bdev = ext3_blkdev_get(j_dev);
        if (bdev == NULL)
                return NULL;
 
        blocksize = sb->s_blocksize;
-       hblock = get_hardsect_size(journal_dev);
+       hblock = get_hardsect_size(j_dev);
        if (blocksize < hblock) {
                printk(KERN_ERR
                        "EXT3-fs: blocksize too small for journal device.\n");
@@ -1286,8 +1285,8 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        
        sb_block = EXT3_MIN_BLOCK_SIZE / blocksize;
        offset = EXT3_MIN_BLOCK_SIZE % blocksize;
-       set_blocksize(dev, blocksize);
-       if (!(bh = bread(dev, sb_block, blocksize))) {
+       set_blocksize(j_dev, blocksize);
+       if (!(bh = bread(j_dev, sb_block, blocksize))) {
                printk(KERN_ERR "EXT3-fs: couldn't read superblock of "
                       "external journal\n");
                goto out_bdev;
@@ -1313,7 +1312,7 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
        start = sb_block + 1;
        brelse(bh);     /* we're done with the superblock */
 
-       journal = journal_init_dev(journal_dev, sb->s_dev, 
+       journal = journal_init_dev(j_dev, sb->s_dev,
                                        start, len, blocksize);
        if (!journal) {
                printk(KERN_ERR "EXT3-fs: failed to create device journal\n");
@@ -1345,7 +1344,7 @@ static int ext3_load_journal(struct super_block * sb,
 {
        journal_t *journal;
        int journal_inum = le32_to_cpu(es->s_journal_inum);
-       int journal_dev = le32_to_cpu(es->s_journal_dev);
+       kdev_t journal_dev = to_kdev_t(le32_to_cpu(es->s_journal_dev));
        int err = 0;
        int really_read_only;
 
@@ -1371,7 +1370,7 @@ static int ext3_load_journal(struct super_block * sb,
                }
        }
 
-       if (journal_inum && journal_dev) {
+       if (journal_inum && !kdev_none(journal_dev)) {
                printk(KERN_ERR "EXT3-fs: filesystem has both journal "
                       "and inode journals!\n");
                return -EINVAL;
index 3cda7afc3650c657eed08d919abd5a1451cda294..f6b81d5748f611dbaaae289ec11b91c0b40ee91f 100644 (file)
@@ -310,8 +310,8 @@ hfs_s32 hfs_do_read(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos,
 
        bhb = bhe = buflist;
        if (reada) {
-               if (blocks < read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9)) {
-                       blocks = read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9);
+               if (blocks < read_ahead[major(dev)] / (HFS_SECTOR_SIZE>>9)) {
+                       blocks = read_ahead[major(dev)] / (HFS_SECTOR_SIZE>>9);
                }
                if (block + blocks > size) {
                        blocks = size - block;
index 9fdfedc226bb48bc31bcfb849e18f54d8014881e..0785b7d8a1652dd274c1165e63c747e57a70ff0f 100644 (file)
@@ -78,12 +78,12 @@ static inline struct upc_comm *presto_psdev_f2u(struct file *file)
 {
         int minor;
 
-        if ( MAJOR(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
+        if ( major(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
                 EXIT;
                 return NULL;
         }
 
-        minor = MINOR(file->f_dentry->d_inode->i_rdev);
+        minor = minor(file->f_dentry->d_inode->i_rdev);
         if ( minor < 0 || minor >= MAX_PRESTODEV ) {
                 EXIT;
                 return NULL;
index a0d17cbf9edf2bc7fdade9908b41e0897876472c..2b011f1711f2dd7ee2ae14cb4792c8355a626f85 100644 (file)
@@ -159,7 +159,7 @@ static int presto_get_minor(char *dev_path, int *minor)
 {
         struct nameidata nd;
         struct dentry *dentry;
-        kdev_t devno = 0;
+        kdev_t devno = NODEV;
         int error; 
         ENTRY;
 
@@ -188,19 +188,19 @@ static int presto_get_minor(char *dev_path, int *minor)
        }
 
         devno = dentry->d_inode->i_rdev;
-        if ( MAJOR(devno) != PRESTO_PSDEV_MAJOR ) { 
+        if ( major(devno) != PRESTO_PSDEV_MAJOR ) { 
                EXIT;
                goto out;
        }
 
-        if ( MINOR(devno) >= MAX_PRESTODEV ) {
+        if ( minor(devno) >= MAX_PRESTODEV ) {
                EXIT;
                goto out;
        }
 
        EXIT;
  out:
-        *minor = MINOR(devno);
+        *minor = minor(devno);
         path_release(&nd);
         return 0;
 }
index d24eb020285cb975cf353819fce1b00e3e3d4adb..a348ba9f2d256b8d5561005c80362347e970dd57 100644 (file)
@@ -81,7 +81,7 @@ jffs_read_super(struct super_block *sb, void *data, int silent)
        D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
                  kdevname(dev)));
 
-       if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
+       if (major(dev) != MTD_BLOCK_MAJOR) {
                printk(KERN_WARNING "JFFS: Trying to mount a "
                       "non-mtd device.\n");
                return 0;
index 1b0c24da2de6142a9c9f1421aac25578558827de..c40a8fb0a45b3f4762231bd6c32c7447ea135859 100644 (file)
@@ -795,7 +795,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in
        
        if ((mode & S_IFMT) == S_IFBLK ||
            (mode & S_IFMT) == S_IFCHR) {
-               dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev));
+               dev = (MAJOR(rdev) << 8) | MINOR(rdev);
                devlen = sizeof(dev);
        }
        
index f9d2d257fbf0ed46f4c276d51e68bd02f42c29e3..4771c02ee965bfe758438ae65620dcbfb5d9ca07 100644 (file)
@@ -105,8 +105,8 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
        if ((inode->i_mode & S_IFMT) == S_IFBLK ||
            (inode->i_mode & S_IFMT) == S_IFCHR) {
                /* For these, we don't actually need to read the old node */
-               dev =  (MAJOR(to_kdev_t(dentry->d_inode->i_rdev)) << 8) | 
-                       MINOR(to_kdev_t(dentry->d_inode->i_rdev));
+               dev =  (major(dentry->d_inode->i_rdev) << 8) | 
+                       minor(dentry->d_inode->i_rdev);
                mdata = (char *)&dev;
                mdatalen = sizeof(dev);
                D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
index 17a7fd4172b69e7c14079bbe2d28c2afc78984e4..4cdb2855759b97ec13899ae212c12a0440fce28e 100644 (file)
@@ -269,8 +269,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
        if ((inode->i_mode & S_IFMT) == S_IFBLK ||
            (inode->i_mode & S_IFMT) == S_IFCHR) {
                /* For these, we don't actually need to read the old node */
-               dev =  (MAJOR(to_kdev_t(inode->i_rdev)) << 8) | 
-                       MINOR(to_kdev_t(inode->i_rdev));
+               dev =  (major(inode->i_rdev) << 8) | 
+                       minor(inode->i_rdev);
                mdata = (char *)&dev;
                mdatalen = sizeof(dev);
                D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
index c4cf156408432f50f8c748defa02ef9be209ea50..ef79d201282bb99c3c6f8885d66a72684d23ff07 100644 (file)
@@ -199,7 +199,7 @@ static struct super_block *jffs2_read_super(struct super_block *sb, void *data,
 
        D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev)));
 
-       if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
+       if (major(sb->s_dev) != MTD_BLOCK_MAJOR) {
                if (!silent)
                        printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev));
                return NULL;
index 5113acea59c7c058428fea1ee597924f22fdd897..20d3add2cf42b1878984d10c07c572dcb948686c 100644 (file)
@@ -1589,7 +1589,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
                goto exit_lock;
 
        error = -EXDEV;
-       if (!kdev_same(dir->i_dev, inode->i_dev))
+       if (dir->i_sb != inode->i_sb)
                goto exit_lock;
 
        /*
@@ -1707,7 +1707,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
        if (error)
                return error;
 
-       if (!kdev_same(new_dir->i_dev, old_dir->i_dev))
+       if (new_dir->i_sb != old_dir->i_sb)
                return -EXDEV;
 
        if (!new_dentry->d_inode)
@@ -1787,7 +1787,7 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
        if (error)
                return error;
 
-       if (!kdev_same(new_dir->i_dev, old_dir->i_dev))
+       if (new_dir->i_sb != old_dir->i_sb)
                return -EXDEV;
 
        if (!new_dentry->d_inode)
index 37b4e581ecbf766baaa32ec1730f9406283d4cea..4054697f6c93f95af906d18b2fb2a47c8bd3b02d 100644 (file)
@@ -181,7 +181,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
        inode->i_nlink = 1;
        inode->i_uid = server->m.uid;
        inode->i_gid = server->m.gid;
-       inode->i_rdev = 0;
+       inode->i_rdev = NODEV;
        inode->i_blksize = NCP_BLOCK_SIZE;
 
        inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
index 9589e2f2959445fcc0eef79364d22142b001d5ab..83f616b739dfd6b64ec152da252cf9d87fe1955c 100644 (file)
@@ -1201,8 +1201,9 @@ nfs_commit_done(struct rpc_task *task)
                req = nfs_list_entry(data->pages.next);
                nfs_list_remove_request(req);
 
-               dprintk("NFS: commit (%x/%Ld %d@%Ld)",
-                       req->wb_inode->i_dev,
+               dprintk("NFS: commit (%02x:%02x/%Ld %d@%Ld)",
+                       major(req->wb_inode->i_dev),
+                       minor(req->wb_inode->i_dev),
                        (long long)NFS_FILEID(req->wb_inode),
                        req->wb_bytes,
                        (long long)(page_offset(req->wb_page) + req->wb_offset));
index e3b037803b0e6df12e1120a7364a234ffffc3ff0..834974627f61b9a134cfa07e26f207ccf793f656 100644 (file)
@@ -173,9 +173,9 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
                p = xdr_encode_hyper(p, (u64)(inode->i_size +511)& ~511);
        else
                p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
-       *p++ = htonl((u32) MAJOR(inode->i_rdev));
-       *p++ = htonl((u32) MINOR(inode->i_rdev));
-       p = xdr_encode_hyper(p, (u64) inode->i_dev);
+       *p++ = htonl((u32) major(inode->i_rdev));
+       *p++ = htonl((u32) minor(inode->i_rdev));
+       p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
        p = xdr_encode_hyper(p, (u64) inode->i_ino);
        p = encode_time3(p, inode->i_atime);
        p = encode_time3(p, lease_get_mtime(inode));
@@ -203,9 +203,9 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
                p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
        }
        p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
-       *p++ = htonl((u32) MAJOR(fhp->fh_post_rdev));
-       *p++ = htonl((u32) MINOR(fhp->fh_post_rdev));
-       p = xdr_encode_hyper(p, (u64) inode->i_dev);
+       *p++ = htonl((u32) major(fhp->fh_post_rdev));
+       *p++ = htonl((u32) minor(fhp->fh_post_rdev));
+       p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
        p = xdr_encode_hyper(p, (u64) inode->i_ino);
        p = encode_time3(p, fhp->fh_post_atime);
        p = encode_time3(p, fhp->fh_post_mtime);
index c33f6530db04e56108ab5971c45e506e8e2c4cd4..cccf3980546e1ed404c556a3f48cd11ec4f9a497 100644 (file)
@@ -28,7 +28,7 @@ adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
        extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
                                    unsigned long, unsigned int);
 
-       if (MAJOR(dev) == MFM_ACORN_MAJOR) {
+       if (major(dev) == MFM_ACORN_MAJOR) {
                unsigned long totalblocks = hd->part[MINOR(dev)].nr_sects;
                xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
        }
index cc6e7470eb7f0afaa3be5fb4fe0d0822590026ef..96706f2cedf168d761ca528578dd907d54ff75c0 100644 (file)
@@ -125,7 +125,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
                return 0;
        if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
                return 0;
-       blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+       blocksize = hardsect_size[major(dev)][minor(dev)];
        if ( blocksize <= 0 ) {
                return 0;
        }
index 161ee269273af68b4dd33be5f0d60383e9d8ec3f..afe762afe224519f32dbb5becff8b70b231ca641 100644 (file)
@@ -518,7 +518,9 @@ romfs_read_inode(struct inode *i)
                default:
                        /* depending on MBZ for sock/fifos */
                        nextfh = ntohl(ri.spec);
-                       nextfh = kdev_t_to_nr(MKDEV(nextfh>>16,nextfh&0xffff));
+                       /* convert back and forth for typechecking and
+                        * source tagging */
+                       nextfh = kdev_t_to_nr(mk_kdev(nextfh>>16,nextfh&0xffff));
                        init_special_inode(i, ino, nextfh);
        }
 }
index 63ecf3d06cafd5e5026882d538478eca85bda613..1ad88890be22706302c48289092695412c29fcc9 100644 (file)
@@ -1,5 +1,15 @@
 ChangeLog for smbfs.
 
+2001-12-31 René Scharfe <l.s.r@web.de>
+
+       * inode.c: added smb_show_options to show mount options in /proc/mounts
+       * inode.c, getopt.c, getopt.h: merged flag and has_arg in struct option
+       * inode.c: use S_IRWXUGO where appropriate
+
+2001-12-22 Urban Widmark <urban@teststation.com>
+
+       * file.c, proc.c: Fix problems triggered by the "fsx test"
+
 2001-09-17 Urban Widmark <urban@teststation.com>
 
        * proc.c: Use 4096 (was 512) as the blocksize for better write
index d74e32ad6bf52079b162f6a469e0fa15d99513c4..6f1214176be0a58d8370a85c3891406620080377 100644 (file)
@@ -270,7 +270,6 @@ out:
 static int smb_prepare_write(struct file *file, struct page *page, 
                             unsigned offset, unsigned to)
 {
-       kmap(page);
        return 0;
 }
 
@@ -283,7 +282,6 @@ static int smb_commit_write(struct file *file, struct page *page,
        lock_kernel();
        status = smb_updatepage(file, page, offset, to-offset);
        unlock_kernel();
-       kunmap(page);
        return status;
 }
 
@@ -349,8 +347,14 @@ static int
 smb_file_release(struct inode *inode, struct file * file)
 {
        lock_kernel();
-       if (!--inode->u.smbfs_i.openers)
+       if (!--inode->u.smbfs_i.openers) {
+               /* We must flush any dirty pages now as we won't be able to
+                  write anything after close. mmap can trigger this.
+                  "openers" should perhaps include mmap'ers ... */
+               filemap_fdatasync(inode->i_mapping);
+               filemap_fdatawait(inode->i_mapping);
                smb_close(inode);
+       }
        unlock_kernel();
        return 0;
 }
index 20276da095bf8b0d0179bc27b37c03a876dbc0f2..626543fb8ac6ee80fd2150679bce67dc6767e21f 100644 (file)
@@ -46,7 +46,7 @@ int smb_getopt(char *caller, char **options, struct option *opts,
 
        for (i = 0; opts[i].name != NULL; i++) {
                if (!strcmp(opts[i].name, token)) {
-                       if (opts[i].has_arg && (!val || !*val)) {
+                       if (!opts[i].flag && (!val || !*val)) {
                                printk("%s: the %s option requires an argument\n",
                                       caller, token);
                                return -1;
index 691f21103c499e96562519287a64cf9223863c03..146219ac7c46cb113bfac033f215055a785c5c07 100644 (file)
@@ -3,7 +3,6 @@
 
 struct option {
        const char *name;
-       int has_arg;
        unsigned long flag;
        int val;
 };
index 9f5921c18fb5d11a8a5c29216f79690d30c8f9bd..6b3648f890b1dcaea4e7f6bdb9ad165a28d26cb6 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/dcache.h>
 #include <linux/smp_lock.h>
 #include <linux/nls.h>
+#include <linux/seq_file.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
 #define SMB_NLS_REMOTE ""
 #endif
 
+#define SMB_TTL_DEFAULT 1000
+
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct super_block *, struct statfs *);
+static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
 static struct super_operations smb_sops =
 {
@@ -51,6 +55,7 @@ static struct super_operations smb_sops =
        delete_inode:   smb_delete_inode,
        put_super:      smb_put_super,
        statfs:         smb_statfs,
+       show_options:   smb_show_options,
 };
 
 
@@ -259,21 +264,20 @@ smb_delete_inode(struct inode *ino)
        clear_inode(ino);
 }
 
-/* FIXME: flags and has_arg could probably be merged. */
 static struct option opts[] = {
-       { "version",    1, 0, 'v' },
-       { "win95",      0, SMB_MOUNT_WIN95, 1 },
-       { "oldattr",    0, SMB_MOUNT_OLDATTR, 1 },
-       { "dirattr",    0, SMB_MOUNT_DIRATTR, 1 },
-       { "case",       0, SMB_MOUNT_CASE, 1 },
-       { "uid",        1, 0, 'u' },
-       { "gid",        1, 0, 'g' },
-       { "file_mode",  1, 0, 'f' },
-       { "dir_mode",   1, 0, 'd' },
-       { "iocharset",  1, 0, 'i' },
-       { "codepage",   1, 0, 'c' },
-       { "ttl",        1, 0, 't' },
-       { NULL,         0, 0, 0}
+       { "version",    0, 'v' },
+       { "win95",      SMB_MOUNT_WIN95, 1 },
+       { "oldattr",    SMB_MOUNT_OLDATTR, 1 },
+       { "dirattr",    SMB_MOUNT_DIRATTR, 1 },
+       { "case",       SMB_MOUNT_CASE, 1 },
+       { "uid",        0, 'u' },
+       { "gid",        0, 'g' },
+       { "file_mode",  0, 'f' },
+       { "dir_mode",   0, 'd' },
+       { "iocharset",  0, 'i' },
+       { "codepage",   0, 'c' },
+       { "ttl",        0, 't' },
+       { NULL,         0, 0}
 };
 
 static int
@@ -310,12 +314,10 @@ parse_options(struct smb_mount_data_kernel *mnt, char *options)
                        mnt->gid = value;
                        break;
                case 'f':
-                       mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-                       mnt->file_mode |= S_IFREG;
+                       mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
                        break;
                case 'd':
-                       mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-                       mnt->dir_mode |= S_IFDIR;
+                       mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
                        break;
                case 'i':
                        strncpy(mnt->codepage.local_name, optarg, 
@@ -338,6 +340,45 @@ parse_options(struct smb_mount_data_kernel *mnt, char *options)
        return c;
 }
 
+/*
+ * smb_show_options() is for displaying mount options in /proc/mounts.
+ * It tries to avoid showing settings that were not changed from their
+ * defaults.
+ */
+static int
+smb_show_options(struct seq_file *s, struct vfsmount *m)
+{
+       struct smb_mount_data_kernel *mnt = m->mnt_sb->u.smbfs_sb.mnt;
+       int i;
+
+       for (i = 0; opts[i].name != NULL; i++)
+               if (mnt->flags & opts[i].flag)
+                       seq_printf(s, ",%s", opts[i].name);
+
+       if (mnt->uid != 0)
+               seq_printf(s, ",uid=%d", mnt->uid);
+       if (mnt->gid != 0)
+               seq_printf(s, ",gid=%d", mnt->gid);
+       if (mnt->mounted_uid != 0)
+               seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
+
+       /* 
+        * Defaults for file_mode and dir_mode are unknown to us; they
+        * depend on the current umask of the user doing the mount.
+        */
+       seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
+       seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
+
+       if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
+               seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
+       if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
+               seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
+
+       if (mnt->ttl != SMB_TTL_DEFAULT)
+               seq_printf(s, ",ttl=%d", mnt->ttl);
+
+       return 0;
+}
 
 static void
 smb_put_super(struct super_block *sb)
@@ -425,7 +466,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
        strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
                SMB_NLS_MAXNAMELEN);
 
-       mnt->ttl = 1000;
+       mnt->ttl = SMB_TTL_DEFAULT;
        if (ver == SMB_MOUNT_OLDVERSION) {
                mnt->version = oldmnt->version;
 
@@ -434,12 +475,8 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
                mnt->uid = oldmnt->uid;
                mnt->gid = oldmnt->gid;
 
-               mnt->file_mode =
-                       oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-               mnt->dir_mode =
-                       oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-               mnt->file_mode |= S_IFREG;
-               mnt->dir_mode  |= S_IFDIR;
+               mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
+               mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
 
                mnt->flags = (oldmnt->file_mode >> 9);
        } else {
@@ -510,7 +547,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
        struct smb_sb_info *server = server_from_dentry(dentry);
-       unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
+       unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
        int error, changed, refresh = 0;
        struct smb_fattr fattr;
 
@@ -535,6 +572,10 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
                VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
                        DENTRY_PATH(dentry),
                        (long) inode->i_size, (long) attr->ia_size);
+
+               filemap_fdatasync(inode->i_mapping);
+               filemap_fdatawait(inode->i_mapping);
+
                error = smb_open(dentry, O_WRONLY);
                if (error)
                        goto out;
index 98009bff861feda32542ca97e8e99d0c365db47b..cbe1b4ee44a3143ac0d3d327b14bcbea347ce9c3 100644 (file)
@@ -49,7 +49,7 @@ void UMSDOS_put_inode (struct inode *inode)
 void UMSDOS_put_super (struct super_block *sb)
 {
        Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
-       if (saved_root && pseudo_root && sb->s_dev == ROOT_DEV) {
+       if (saved_root && pseudo_root && kdev_same(sb->s_dev, ROOT_DEV)) {
                shrink_dcache_parent(saved_root);
                dput(saved_root);
                saved_root = NULL;
@@ -414,7 +414,7 @@ static struct dentry *check_pseudo_root(struct super_block *sb)
         * must check like this, because we can be used with initrd
         */
                
-       if (sb->s_dev != ROOT_DEV)
+       if (!kdev_same(sb->s_dev, ROOT_DEV))
                goto out_noroot;
 
        /* 
index 2b8cebfa07ca43814da761cff8c798f82f7337e6..efede40e24083b179428de4eb648a9b67928f6fe 100644 (file)
@@ -2,6 +2,7 @@
 #define _BLK_H
 
 #include <linux/blkdev.h>
+#include <linux/elevator.h>
 #include <linux/locks.h>
 #include <linux/config.h>
 #include <linux/spinlock.h>
@@ -43,9 +44,10 @@ extern void end_that_request_last(struct request *);
 static inline void blkdev_dequeue_request(struct request *req)
 {
        list_del(&req->queuelist);
-}
 
-#define __elv_next_request(q)  (q)->elevator.elevator_next_req_fn((q))
+       if (req->q)
+               elv_remove_request(req->q, req);
+}
 
 extern inline struct request *elv_next_request(request_queue_t *q)
 {
@@ -79,21 +81,21 @@ extern inline struct request *elv_next_request(request_queue_t *q)
        return rq;
 }
 
-#define __elv_add_request_core(q, rq, where, plug)                     \
+#define _elv_add_request_core(q, rq, where, plug)                      \
        do {                                                            \
                if ((plug))                                             \
                        blk_plug_device((q));                           \
                (q)->elevator.elevator_add_req_fn((q), (rq), (where));  \
        } while (0)
 
-#define __elv_add_request(q, rq, back, p) do {                               \
+#define _elv_add_request(q, rq, back, p) do {                                \
        if ((back))                                                           \
-               __elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
+               _elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
        else                                                                  \
-               __elv_add_request_core((q), (rq), &(q)->queue_head, 0);       \
+               _elv_add_request_core((q), (rq), &(q)->queue_head, 0);        \
 } while (0)
 
-#define elv_add_request(q, rq, back) __elv_add_request((q), (rq), (back), 1)
+#define elv_add_request(q, rq, back) _elv_add_request((q), (rq), (back), 1)
        
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
index 8c3033d1dd688c59b04caba56ea491f7c8bb93ae..3f11ceb302dfe338cbb1206c703a649825390184 100644 (file)
@@ -25,7 +25,7 @@ struct request {
        struct list_head queuelist; /* looking for ->queue? you must _not_
                                     * access it directly, use
                                     * blkdev_dequeue_request! */
-       int elevator_sequence;
+       void *elevator_private;
 
        unsigned char cmd[16];
 
index 95e4145aa3ad60e1646c0b78fc0787916c32a9df..44cbb0e8e8fe21e500c8810a74fd0bfc25adb89d 100644 (file)
@@ -11,36 +11,53 @@ typedef void (elevator_merge_req_fn) (struct request *, struct request *);
 typedef struct request *(elevator_next_req_fn) (request_queue_t *);
 
 typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
+typedef int (elevator_queue_empty_fn) (request_queue_t *);
+typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
 
 typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
 typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *);
 
 struct elevator_s
 {
-       int latency[2];
-
        elevator_merge_fn *elevator_merge_fn;
        elevator_merge_cleanup_fn *elevator_merge_cleanup_fn;
        elevator_merge_req_fn *elevator_merge_req_fn;
 
        elevator_next_req_fn *elevator_next_req_fn;
        elevator_add_req_fn *elevator_add_req_fn;
+       elevator_remove_req_fn *elevator_remove_req_fn;
+
+       elevator_queue_empty_fn *elevator_queue_empty_fn;
 
        elevator_init_fn *elevator_init_fn;
        elevator_exit_fn *elevator_exit_fn;
+
+       void *elevator_data;
 };
 
-int elevator_noop_merge(request_queue_t *, struct request **, struct bio *);
-void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int);
-void elevator_noop_merge_req(struct request *, struct request *);
+/*
+ * block elevator interface
+ */
+extern void __elv_add_request(request_queue_t *, struct request *,
+                             struct list_head *);
+extern struct request *__elv_next_request(request_queue_t *);
+extern void elv_merge_cleanup(request_queue_t *, struct request *, int);
+extern int elv_merge(request_queue_t *, struct request **, struct bio *);
+extern void elv_merge_requests(request_queue_t *, struct request *,
+                              struct request *);
+extern void elv_remove_request(request_queue_t *, struct request *);
+
+/*
+ * noop I/O scheduler. always merges, always inserts new request at tail
+ */
+extern elevator_t elevator_noop;
 
-int elevator_linus_merge(request_queue_t *, struct request **, struct bio *);
-void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int);
-void elevator_linus_merge_req(struct request *, struct request *);
-int elv_linus_init(request_queue_t *, elevator_t *);
-void elv_linus_exit(request_queue_t *, elevator_t *);
-struct request *elv_next_request_fn(request_queue_t *);
-void elv_add_request_fn(request_queue_t *, struct request *,struct list_head *);
+/*
+ * elevator linus. based on linus ideas of starvation control, using
+ * sequencing to manage inserts and merges.
+ */
+extern elevator_t elevator_linus;
+#define elv_linus_sequence(rq) ((long)(rq)->elevator_private)
 
 /*
  * use the /proc/iosched interface, all the below is history ->
@@ -64,48 +81,10 @@ extern void elevator_exit(request_queue_t *, elevator_t *);
 #define ELEVATOR_FRONT_MERGE   1
 #define ELEVATOR_BACK_MERGE    2
 
-#define elevator_request_latency(e, rw)        ((e)->latency[(rw) & 1])
-
 /*
  * will change once we move to a more complex data structure than a simple
  * list for pending requests
  */
 #define elv_queue_empty(q)     list_empty(&(q)->queue_head)
 
-/*
- * elevator private data
- */
-struct elv_linus_data {
-       unsigned long flags;
-};
-
-#define ELV_DAT(e) ((struct elv_linus_data *)(e)->elevator_data)
-
-#define ELV_LINUS_BACK_MERGE   1
-#define ELV_LINUS_FRONT_MERGE  2
-
-#define ELEVATOR_NOOP                                                  \
-((elevator_t) {                                                                \
-       { 0, 0},                                                        \
-       elevator_noop_merge,            /* elevator_merge_fn */         \
-       elevator_noop_merge_cleanup,    /* elevator_merge_cleanup_fn */ \
-       elevator_noop_merge_req,        /* elevator_merge_req_fn */     \
-       elv_next_request_fn,                                            \
-       elv_add_request_fn,                                             \
-       elv_linus_init,                                                 \
-       elv_linus_exit,                                                 \
-       })
-
-#define ELEVATOR_LINUS                                                 \
-((elevator_t) {                                                                \
-       { 8192, 16384 },                                                \
-       elevator_linus_merge,           /* elevator_merge_fn */         \
-       elevator_linus_merge_cleanup,   /* elevator_merge_cleanup_fn */ \
-       elevator_linus_merge_req,       /* elevator_merge_req_fn */     \
-       elv_next_request_fn,                                            \
-       elv_add_request_fn,                                             \
-       elv_linus_init,                                                 \
-       elv_linus_exit,                                                 \
-       })
-
 #endif
index e76cd83d297b6ba209b229d82a53f9ef9d997c7b..a8e2d11c46a79dc7010cc22d9cb7fa8339450e1f 100644 (file)
@@ -916,6 +916,12 @@ int ide_system_bus_speed (void);
  */
 int ide_multwrite (ide_drive_t *drive, unsigned int mcount);
 
+/*
+ * idedisk_input_data() is a wrapper around ide_input_data() which copes
+ * with byte-swapping the input data if required.
+ */
+inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+
 /*
  * ide_stall_queue() can be used by a drive to give excess bandwidth back
  * to the hwgroup by sleeping for timeout jiffies.
index e40bddbba7cdfe5d525d1ec42ba50f426231b89e..905f2673680de56b061dd9712029d33961886b59 100644 (file)
@@ -302,7 +302,7 @@ struct task_struct {
  * all fields in a single cacheline that are needed for
  * the goodness() loop in schedule().
  */
-       long dyn_prio;
+       unsigned long dyn_prio;
        long nice;
        unsigned long policy;
        struct mm_struct *mm;
@@ -322,7 +322,6 @@ struct task_struct {
         */
        struct list_head run_list;
        long time_slice;
-       unsigned long sleep_time;
        /* recalculation loop checkpoint */
        unsigned long rcl_last;
 
@@ -453,7 +452,7 @@ struct task_struct {
  */
 #define _STK_LIM       (8*1024*1024)
 
-#define MAX_DYNPRIO    100
+#define MAX_DYNPRIO    40
 #define DEF_TSLICE     (6 * HZ / 100)
 #define MAX_TSLICE     (20 * HZ / 100)
 #define DEF_NICE       (0)
@@ -886,7 +885,6 @@ do {                                                                        \
 static inline void del_from_runqueue(struct task_struct * p)
 {
        nr_running--;
-       p->sleep_time = jiffies;
        list_del(&p->run_list);
        p->run_list.next = NULL;
 }
index 16fe11cf5e9eb8607b02c5ad747118a21a8f68b4..8b7c9e47e4045cb4d346ac569c1a2929132a2712 100644 (file)
@@ -732,15 +732,10 @@ device_write_power(const char * buf, size_t count, loff_t off, void * data)
 
        error = -EINVAL;
 
-       if (!num_args) {
-               printk("have no arguments\n");
+       if (!num_args)
                goto done;
-       }
 
        if (!strnicmp(str_command,"suspend",7)) {
-
-               printk("%s: we know it's a suspend action\n",__FUNCTION__);
-
                if (num_args != 3)
                        goto done;
                if (!strnicmp(str_stage,"notify",6))
@@ -775,8 +770,7 @@ device_write_power(const char * buf, size_t count, loff_t off, void * data)
                        error = dev->driver->resume(dev,int_stage);
                else
                        error = 0;
-       } else
-               printk("%s: couldn't find any thing to do\n",__FUNCTION__);
+       }
  done:
        put_device(dev);
 
index 29ff8ab914920859521d5c80de2b5c8489f7ec8a..f7cf77cedaf99f7ac28e8c950939922002fee7cb 100644 (file)
@@ -51,11 +51,11 @@ extern void mem_use(void);
  * NOTE! The unix "nice" value influences how long a process
  * gets. The nice value ranges from -20 to +19, where a -20
  * is a "high-priority" task, and a "+10" is a low-priority
- * task. The default time slice for zero-nice tasks will be 43ms.
+ * task. The default time slice for zero-nice tasks will be 37ms.
  */
 #define NICE_RANGE     40
-#define MIN_NICE_TSLICE        10000
-#define MAX_NICE_TSLICE        80000
+#define MIN_NICE_TSLICE        5000
+#define MAX_NICE_TSLICE        70000
 #define TASK_TIMESLICE(p)      ((int) ts_table[19 - (p)->nice])
 
 static unsigned char ts_table[NICE_RANGE];
@@ -538,7 +538,7 @@ void expire_task(struct task_struct *p)
                goto need_resched;
 
        if (!--p->time_slice) {
-               if (p->dyn_prio > 0) {
+               if (p->dyn_prio) {
                        p->time_slice--;
                        p->dyn_prio--;
                }
@@ -1070,7 +1070,8 @@ asmlinkage long sys_sched_yield(void)
                current->need_resched = 1;
 
                current->time_slice = 0;
-               current->dyn_prio++;
+               if (++current->dyn_prio > MAX_DYNPRIO)
+                       current->dyn_prio = MAX_DYNPRIO;
        }
        return 0;
 }
@@ -1323,9 +1324,12 @@ static void fill_tslice_map(void)
 {
        int i;
 
-       for (i = 0; i < NICE_RANGE; i++)
+       for (i = 0; i < NICE_RANGE; i++) {
                ts_table[i] = ((MIN_NICE_TSLICE +
-                                               ((MAX_NICE_TSLICE - MIN_NICE_TSLICE) / NICE_RANGE) * i) * HZ) / 1000000;
+                                               ((MAX_NICE_TSLICE -
+                                                 MIN_NICE_TSLICE) / (NICE_RANGE - 1)) * i) * HZ) / 1000000;
+               if (!ts_table[i]) ts_table[i] = 1;
+       }
 }
 
 void __init sched_init(void)
index 6ab868779dd2608e28a7caf843589df7819d95d6..8271b50fa5085f72a50107f0f376b858636b3da8 100644 (file)
@@ -386,13 +386,13 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
 static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
 {
        struct ircomm_tty_cb *self;
-       int line;
+       unsigned int line;
        int ret;
 
        IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
        MOD_INC_USE_COUNT;
-       line = MINOR(tty->device) - tty->driver.minor_start;
+       line = minor(tty->device) - tty->driver.minor_start;
        if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
                MOD_DEC_USE_COUNT;
                return -ENODEV;
index 2fe27330bd093838c0c2b41dbe9c08729efca3e2..be392c2ce573e2fed880c5038bec81f45675752f 100644 (file)
@@ -41,7 +41,7 @@ static struct socket *netlink_user[MAX_LINKS];
  
 static unsigned int netlink_poll(struct file *file, poll_table * wait)
 {
-       struct socket *sock = netlink_user[MINOR(file->f_dentry->d_inode->i_rdev)];
+       struct socket *sock = netlink_user[minor(file->f_dentry->d_inode->i_rdev)];
 
        if (sock->ops->poll==NULL)
                return 0;
@@ -56,7 +56,7 @@ static ssize_t netlink_write(struct file * file, const char * buf,
                             size_t count, loff_t *pos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct socket *sock = netlink_user[MINOR(inode->i_rdev)];
+       struct socket *sock = netlink_user[minor(inode->i_rdev)];
        struct msghdr msg;
        struct iovec iov;
 
@@ -80,7 +80,7 @@ static ssize_t netlink_read(struct file * file, char * buf,
                            size_t count, loff_t *pos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct socket *sock = netlink_user[MINOR(inode->i_rdev)];
+       struct socket *sock = netlink_user[minor(inode->i_rdev)];
        struct msghdr msg;
        struct iovec iov;
 
@@ -105,7 +105,7 @@ static loff_t netlink_lseek(struct file * file, loff_t offset, int origin)
 
 static int netlink_open(struct inode * inode, struct file * file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct socket *sock;
        struct sockaddr_nl nladdr;
        int err;
@@ -137,7 +137,7 @@ out:
 
 static int netlink_release(struct inode * inode, struct file * file)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        struct socket *sock;
 
        sock = netlink_user[minor];
@@ -151,7 +151,7 @@ static int netlink_release(struct inode * inode, struct file * file)
 static int netlink_ioctl(struct inode *inode, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
-       unsigned int minor = MINOR(inode->i_rdev);
+       unsigned int minor = minor(inode->i_rdev);
        int retval = 0;
 
        if (minor >= MAX_LINKS)