## Automatically generated incremental diff ## From: linux-2.5.2-pre6 ## To: linux-2.5.2-pre7 ## Robot: $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $ diff -urN linux-2.5.2-pre6/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.5.2-pre6/Documentation/Configure.help Fri Nov 30 13:25:10 2001 +++ linux/Documentation/Configure.help Thu Jan 3 14:10:35 2002 @@ -12541,6 +12541,30 @@ 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 . + + 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 . + UHCI (Intel PIIX4, VIA, ...) support CONFIG_USB_UHCI The Universal Host Controller Interface is a standard by Intel for @@ -12841,6 +12865,17 @@ The module will be called visor.o. If you want to compile it as a module, say M here and read . +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 . + + 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 . + 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 @@ The module will be called io_edgeport.o. If you want to compile it as a module, say M here and read . +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 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 . + 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 @@ The module will be called pwc.o. If you want to compile it as a module, say M here and read . +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 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 . + + 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 . + +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 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 . + + 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 . + +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 . + + 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 . + + 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. @@ -16960,22 +17059,6 @@ Note that, even if you say N here, Linux on the x86 architecture 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 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 . - - 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 . ACPI support CONFIG_ACPI diff -urN linux-2.5.2-pre6/Documentation/usb/ehci.txt linux/Documentation/usb/ehci.txt --- linux-2.5.2-pre6/Documentation/usb/ehci.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/ehci.txt Thu Jan 3 14:10:35 2002 @@ -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 + + + +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 -urN linux-2.5.2-pre6/Documentation/usb/stv680.txt linux/Documentation/usb/stv680.txt --- linux-2.5.2-pre6/Documentation/usb/stv680.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/stv680.txt Thu Jan 3 14:10:35 2002 @@ -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 + + diff -urN linux-2.5.2-pre6/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- linux-2.5.2-pre6/Documentation/usb/usb-serial.txt Mon Nov 12 09:50:39 2001 +++ linux/Documentation/usb/usb-serial.txt Thu Jan 3 14:10:35 2002 @@ -95,6 +95,66 @@ 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 + + Keyspan PDA Serial Adapter Single port DB-9 serial adapter, pushed as a PDA adapter for iMacs (mostly @@ -301,6 +361,32 @@ For any questions or problems with this driver, please contact Greg 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 diff -urN linux-2.5.2-pre6/Makefile linux/Makefile --- linux-2.5.2-pre6/Makefile Thu Jan 3 14:10:32 2002 +++ linux/Makefile Thu Jan 3 14:10:35 2002 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 2 -EXTRAVERSION =-pre6 +EXTRAVERSION =-pre7 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -urN linux-2.5.2-pre6/arch/i386/kernel/cpuid.c linux/arch/i386/kernel/cpuid.c --- linux-2.5.2-pre6/arch/i386/kernel/cpuid.c Thu Oct 11 09:04:57 2001 +++ linux/arch/i386/kernel/cpuid.c Thu Jan 3 14:10:35 2002 @@ -101,7 +101,7 @@ 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 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)) ) diff -urN linux-2.5.2-pre6/arch/i386/kernel/msr.c linux/arch/i386/kernel/msr.c --- linux-2.5.2-pre6/arch/i386/kernel/msr.c Thu Oct 11 09:04:57 2001 +++ linux/arch/i386/kernel/msr.c Thu Jan 3 14:10:35 2002 @@ -181,7 +181,7 @@ 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 @@ 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 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)) ) diff -urN linux-2.5.2-pre6/drivers/block/DAC960.h linux/drivers/block/DAC960.h --- linux-2.5.2-pre6/drivers/block/DAC960.h Tue Nov 27 09:23:27 2001 +++ linux/drivers/block/DAC960.h Thu Jan 3 14:10:36 2002 @@ -2054,13 +2054,13 @@ */ #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)) diff -urN linux-2.5.2-pre6/drivers/block/cciss.c linux/drivers/block/cciss.c --- linux-2.5.2-pre6/drivers/block/cciss.c Thu Jan 3 14:10:32 2002 +++ linux/drivers/block/cciss.c Thu Jan 3 14:10:36 2002 @@ -317,8 +317,8 @@ */ 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 @@ 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 @@ * 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_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_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 @@ 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 @@ 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 @@ hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON); cciss_geninit(ctlr); - for(i=0; isizes[ i<usage_count--; return 0; @@ -1205,7 +1207,6 @@ 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 @@ 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 @@ 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 @@ cciss_geninit(i); for(j=0; jgendisk), - MKDEV(MAJOR_NR+i, j <<4), + mk_kdev(MAJOR_NR+i, j <<4), MAX_PART, &cciss_fops, hba[i]->drv[j].nr_blocks); diff -urN linux-2.5.2-pre6/drivers/block/cciss_cmd.h linux/drivers/block/cciss_cmd.h --- linux-2.5.2-pre6/drivers/block/cciss_cmd.h Tue Nov 27 09:23:27 2001 +++ linux/drivers/block/cciss_cmd.h Thu Jan 3 14:10:36 2002 @@ -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 diff -urN linux-2.5.2-pre6/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- linux-2.5.2-pre6/drivers/block/cpqarray.c Thu Jan 3 14:10:32 2002 +++ linux/drivers/block/cpqarray.c Thu Jan 3 14:10:36 2002 @@ -499,7 +499,7 @@ ida_geninit(i); for(j=0; jdrv[j].nr_blks); } @@ -776,15 +776,15 @@ */ 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 @@ * 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_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 @@ { 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 @@ 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 @@ 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 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 @@ 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 @@ hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY); ida_geninit(ctlr); - for(i=0; iusage_count--; return 0; @@ -1543,7 +1544,7 @@ 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); diff -urN linux-2.5.2-pre6/drivers/block/elevator.c linux/drivers/block/elevator.c --- linux-2.5.2-pre6/drivers/block/elevator.c Thu Jan 3 14:10:32 2002 +++ linux/drivers/block/elevator.c Thu Jan 3 14:10:36 2002 @@ -121,45 +121,54 @@ 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 @@ /* * 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- linux-2.5.2-pre6/drivers/block/ll_rw_blk.c Thu Jan 3 14:10:32 2002 +++ linux/drivers/block/ll_rw_blk.c Thu Jan 3 14:10:36 2002 @@ -530,8 +530,10 @@ 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 @@ * 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 @@ 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 @@ 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 @@ * 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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; @@ -1195,11 +1198,6 @@ spin_lock_irq(q->queue_lock); 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, diff -urN linux-2.5.2-pre6/drivers/block/loop.c linux/drivers/block/loop.c --- linux-2.5.2-pre6/drivers/block/loop.c Thu Jan 3 14:10:32 2002 +++ linux/drivers/block/loop.c Thu Jan 3 14:10:36 2002 @@ -155,8 +155,8 @@ { 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; diff -urN linux-2.5.2-pre6/drivers/block/rd.c linux/drivers/block/rd.c --- linux-2.5.2-pre6/drivers/block/rd.c Thu Jan 3 14:10:32 2002 +++ linux/drivers/block/rd.c Thu Jan 3 14:10:36 2002 @@ -246,7 +246,7 @@ 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 @@ 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 @@ 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 @@ &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 */ diff -urN linux-2.5.2-pre6/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c --- linux-2.5.2-pre6/drivers/cdrom/sonycd535.c Thu Oct 25 13:58:35 2001 +++ linux/drivers/cdrom/sonycd535.c Thu Jan 3 14:10:36 2002 @@ -217,6 +217,8 @@ 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 @@ 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, ¶ms[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 - * . - */ + 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, ¶ms[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 + * . + */ + /* + * 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 @@ 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 */ diff -urN linux-2.5.2-pre6/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c --- linux-2.5.2-pre6/drivers/char/acquirewdt.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/acquirewdt.c Thu Jan 3 14:10:36 2002 @@ -117,7 +117,7 @@ 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_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 diff -urN linux-2.5.2-pre6/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c --- linux-2.5.2-pre6/drivers/char/advantechwdt.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/advantechwdt.c Thu Jan 3 14:10:36 2002 @@ -128,7 +128,7 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- linux-2.5.2-pre6/drivers/char/busmouse.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/busmouse.c Thu Jan 3 14:10:36 2002 @@ -51,7 +51,7 @@ #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) /* diff -urN linux-2.5.2-pre6/drivers/char/eurotechwdt.c linux/drivers/char/eurotechwdt.c --- linux-2.5.2-pre6/drivers/char/eurotechwdt.c Thu Oct 25 13:53:47 2001 +++ linux/drivers/char/eurotechwdt.c Thu Jan 3 14:10:36 2002 @@ -280,7 +280,7 @@ 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_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 diff -urN linux-2.5.2-pre6/drivers/char/ib700wdt.c linux/drivers/char/ib700wdt.c --- linux-2.5.2-pre6/drivers/char/ib700wdt.c Thu Oct 11 09:07:00 2001 +++ linux/drivers/char/ib700wdt.c Thu Jan 3 14:10:36 2002 @@ -155,7 +155,7 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/char/joystick/serport.c linux/drivers/char/joystick/serport.c --- linux-2.5.2-pre6/drivers/char/joystick/serport.c Wed Sep 12 15:34:06 2001 +++ linux/drivers/char/joystick/serport.c Thu Jan 3 14:10:36 2002 @@ -149,9 +149,9 @@ 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); diff -urN linux-2.5.2-pre6/drivers/char/lp.c linux/drivers/char/lp.c --- linux-2.5.2-pre6/drivers/char/lp.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/lp.c Thu Jan 3 14:10:36 2002 @@ -294,7 +294,7 @@ 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_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 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_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_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; diff -urN linux-2.5.2-pre6/drivers/char/machzwd.c linux/drivers/char/machzwd.c --- linux-2.5.2-pre6/drivers/char/machzwd.c Thu Sep 13 15:21:32 2001 +++ linux/drivers/char/machzwd.c Thu Jan 3 14:10:36 2002 @@ -378,7 +378,7 @@ 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_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(); diff -urN linux-2.5.2-pre6/drivers/char/pcwd.c linux/drivers/char/pcwd.c --- linux-2.5.2-pre6/drivers/char/pcwd.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/pcwd.c Thu Jan 3 14:10:36 2002 @@ -400,7 +400,7 @@ 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 @@ /* 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 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 */ diff -urN linux-2.5.2-pre6/drivers/char/ppdev.c linux/drivers/char/ppdev.c --- linux-2.5.2-pre6/drivers/char/ppdev.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/ppdev.c Thu Jan 3 14:10:36 2002 @@ -103,7 +103,7 @@ 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_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 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_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_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; diff -urN linux-2.5.2-pre6/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- linux-2.5.2-pre6/drivers/char/sysrq.c Mon Dec 10 13:52:53 2001 +++ linux/drivers/char/sysrq.c Thu Jan 3 14:10:36 2002 @@ -105,7 +105,7 @@ /* 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 @@ 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(); diff -urN linux-2.5.2-pre6/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- linux-2.5.2-pre6/drivers/char/tty_io.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/char/tty_io.c Thu Jan 3 14:10:36 2002 @@ -2006,15 +2006,11 @@ 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) ) { diff -urN linux-2.5.2-pre6/drivers/char/wdt.c linux/drivers/char/wdt.c --- linux-2.5.2-pre6/drivers/char/wdt.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/wdt.c Thu Jan 3 14:10:36 2002 @@ -265,7 +265,7 @@ 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_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_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 */ diff -urN linux-2.5.2-pre6/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c --- linux-2.5.2-pre6/drivers/char/wdt_pci.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/char/wdt_pci.c Thu Jan 3 14:10:36 2002 @@ -281,7 +281,7 @@ 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_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_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 */ diff -urN linux-2.5.2-pre6/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c --- linux-2.5.2-pre6/drivers/i2c/i2c-dev.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/i2c/i2c-dev.c Thu Jan 3 14:10:36 2002 @@ -382,7 +382,7 @@ 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 @@ 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 diff -urN linux-2.5.2-pre6/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c --- linux-2.5.2-pre6/drivers/ide/ide-disk.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/ide/ide-disk.c Thu Jan 3 14:10:36 2002 @@ -30,7 +30,7 @@ * Version 1.11 Highmem I/O support, Jens Axboe */ -#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 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) diff -urN linux-2.5.2-pre6/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c --- linux-2.5.2-pre6/drivers/ide/ide-probe.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/ide/ide-probe.c Thu Jan 3 14:10:37 2002 @@ -595,17 +595,18 @@ { 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. */ diff -urN linux-2.5.2-pre6/drivers/ide/ide.c linux/drivers/ide/ide.c --- linux-2.5.2-pre6/drivers/ide/ide.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/ide/ide.c Thu Jan 3 14:10:37 2002 @@ -1241,12 +1241,6 @@ 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 */ diff -urN linux-2.5.2-pre6/drivers/ide/pdc4030.c linux/drivers/ide/pdc4030.c --- linux-2.5.2-pre6/drivers/ide/pdc4030.c Tue Jul 17 18:53:55 2001 +++ linux/drivers/ide/pdc4030.c Thu Jan 3 14:10:37 2002 @@ -66,8 +66,10 @@ * 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 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ __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; } } diff -urN linux-2.5.2-pre6/drivers/input/evdev.c linux/drivers/input/evdev.c --- linux-2.5.2-pre6/drivers/input/evdev.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/input/evdev.c Thu Jan 3 14:10:37 2002 @@ -119,7 +119,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/input/input.c linux/drivers/input/input.c --- linux-2.5.2-pre6/drivers/input/input.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/input/input.c Thu Jan 3 14:10:37 2002 @@ -368,7 +368,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/input/joydev.c linux/drivers/input/joydev.c --- linux-2.5.2-pre6/drivers/input/joydev.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/input/joydev.c Thu Jan 3 14:10:37 2002 @@ -189,7 +189,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/input/mousedev.c linux/drivers/input/mousedev.c --- linux-2.5.2-pre6/drivers/input/mousedev.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/input/mousedev.c Thu Jan 3 14:10:37 2002 @@ -214,7 +214,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/isdn/Config.in linux/drivers/isdn/Config.in --- linux-2.5.2-pre6/drivers/isdn/Config.in Fri Nov 30 09:48:32 2001 +++ linux/drivers/isdn/Config.in Thu Jan 3 14:10:37 2002 @@ -42,6 +42,7 @@ 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 @@ 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 diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h --- linux-2.5.2-pre6/drivers/isdn/avmb1/avmcard.h Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/avmcard.h Thu Jan 3 14:10:37 2002 @@ -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 * @@ -39,13 +39,21 @@ 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]; @@ -543,6 +551,11 @@ 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); diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/b1.c Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/b1.c Thu Jan 3 14:10:37 2002 @@ -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 #include +#include #include #include #include @@ -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 $"; /* ------------------------------------------------------------- */ @@ -638,6 +639,65 @@ } /* ------------------------------------------------------------- */ + +#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); diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/b1dma.c Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/b1dma.c Thu Jan 3 14:10:37 2002 @@ -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 @@ 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 @@ _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 @@ 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 @@ 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 @@ 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 @@ 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 @@ __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 @@ save_flags(flags); cli(); - txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c)); - txaddr -= (__u32)card->dma->sendbuf; - txlen = b1dmainmeml(card->mbase+0x30); - - rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24)); - rxaddr -= (__u32)card->dma->recvbuf; - rxlen = b1dmainmeml(card->mbase+0x28); + txoff = (dma_addr_t)b1dmainmeml(card->mbase+0x2c)-card->dma->sendbuf.dmaaddr; + txlen = b1dmainmeml(card->mbase+0x30); + + 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/b1pci.c Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/b1pci.c Thu Jan 3 14:10:37 2002 @@ -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 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 @@ 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 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 @@ 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 @@ "%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 @@ 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 @@ 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 @@ 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 @@ 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 @@ "%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, ¶m); + retval = b1pciv4_add_card(driver, ¶m, dev); #else - retval = b1pci_add_card(driver, ¶m); + retval = b1pci_add_card(driver, ¶m, dev); #endif if (retval != 0) { printk(KERN_ERR @@ -445,7 +446,7 @@ 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, ¶m); + retval = b1pci_add_card(driver, ¶m, dev); if (retval != 0) { printk(KERN_ERR "%s: no AVM-B1 at i/o %#x, irq %d detected\n", diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/c4.c Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/c4.c Thu Jan 3 14:10:37 2002 @@ -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 @@ 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 @@ _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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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_add_card(struct capi_driver *driver, struct capicardparams *p, + struct pci_dev *dev, int nr) { avmctrl_info *cinfo; @@ -1140,18 +1141,17 @@ 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 @@ "%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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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, ¶m, nr); + retval = c4_add_card(driver, ¶m, dev, nr); if (retval != 0) { printk(KERN_ERR "%s: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n", diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/capi.c Thu Dec 6 14:01:17 2001 +++ linux/drivers/isdn/avmb1/capi.c Thu Jan 3 14:10:37 2002 @@ -129,11 +129,9 @@ }; 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 @@ /* -------- 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 @@ 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 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ { 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 @@ } } endloop: + read_unlock(&capidev_list_lock); *start = page+off; if (len < count) *eof = 1; diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/capifs.c Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/capifs.c Thu Jan 3 14:10:37 2002 @@ -430,7 +430,7 @@ 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)); } } } diff -urN linux-2.5.2-pre6/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c --- linux-2.5.2-pre6/drivers/isdn/avmb1/t1pci.c Sun Sep 30 12:26:05 2001 +++ linux/drivers/isdn/avmb1/t1pci.c Thu Jan 3 14:10:37 2002 @@ -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 @@ 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 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 @@ 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 @@ "%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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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, ¶m); + retval = t1pci_add_card(driver, ¶m, dev); if (retval != 0) { printk(KERN_ERR "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", diff -urN linux-2.5.2-pre6/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile --- linux-2.5.2-pre6/drivers/isdn/hisax/Makefile Fri Nov 30 09:48:32 2001 +++ linux/drivers/isdn/hisax/Makefile Thu Jan 3 14:10:37 2002 @@ -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 diff -urN linux-2.5.2-pre6/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c --- linux-2.5.2-pre6/drivers/isdn/hisax/config.c Fri Nov 30 09:48:32 2001 +++ linux/drivers/isdn/hisax/config.c Thu Jan 3 14:10:37 2002 @@ -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 @@ -336,27 +336,19 @@ 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 @@ #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 @@ 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 @@ } 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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; diff -urN linux-2.5.2-pre6/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h --- linux-2.5.2-pre6/drivers/isdn/hisax/hisax.h Thu Jan 3 14:10:33 2002 +++ linux/drivers/isdn/hisax/hisax.h Thu Jan 3 14:10:37 2002 @@ -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 * @@ -948,8 +948,6 @@ #define MON1_RX 2 #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 diff -urN linux-2.5.2-pre6/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- linux-2.5.2-pre6/drivers/isdn/isdn_common.c Fri Nov 9 13:41:41 2001 +++ linux/drivers/isdn/isdn_common.c Thu Jan 3 14:10:37 2002 @@ -963,7 +963,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) { diff -urN linux-2.5.2-pre6/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- linux-2.5.2-pre6/drivers/isdn/isdn_ppp.c Fri Nov 9 13:41:41 2001 +++ linux/drivers/isdn/isdn_ppp.c Thu Jan 3 14:10:37 2002 @@ -586,7 +586,7 @@ 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); diff -urN linux-2.5.2-pre6/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c --- linux-2.5.2-pre6/drivers/isdn/isdn_tty.c Fri Nov 9 13:41:41 2001 +++ linux/drivers/isdn/isdn_tty.c Thu Jan 3 14:10:37 2002 @@ -1019,12 +1019,12 @@ #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 @@ 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]; diff -urN linux-2.5.2-pre6/drivers/media/video/cpia.c linux/drivers/media/video/cpia.c --- linux-2.5.2-pre6/drivers/media/video/cpia.c Thu Oct 25 13:53:47 2001 +++ linux/drivers/media/video/cpia.c Thu Jan 3 14:10:37 2002 @@ -2386,7 +2386,7 @@ 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 */ diff -urN linux-2.5.2-pre6/drivers/media/video/videodev.c linux/drivers/media/video/videodev.c --- linux-2.5.2-pre6/drivers/media/video/videodev.c Thu Oct 11 09:14:32 2001 +++ linux/drivers/media/video/videodev.c Thu Jan 3 14:10:37 2002 @@ -70,7 +70,7 @@ 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_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 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 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 @@ { 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_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 @@ 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, diff -urN linux-2.5.2-pre6/drivers/net/de2104x.c linux/drivers/net/de2104x.c --- linux-2.5.2-pre6/drivers/net/de2104x.c Mon Dec 10 11:17:40 2001 +++ linux/drivers/net/de2104x.c Thu Jan 3 14:10:37 2002 @@ -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 #include @@ -45,6 +45,7 @@ #include #include #include +#include /* These identify the driver base version and may not be removed. */ static char version[] __initdata = @@ -99,6 +100,7 @@ #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 @@ #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 @@ #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 @@ 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 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_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 @@ dw32(MacStatus, dr32(MacStatus)); - synchronize_irq(); udelay(10); de->rx_tail = 0; @@ -968,15 +974,29 @@ 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 @@ 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 @@ 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 @@ { 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 @@ /* 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 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 @@ } 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 @@ { 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ } } -/* 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 @@ 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 @@ 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 @@ /* 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 @@ goto bad_srom; } + de->media[idx].type = idx; + + 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 = ib->csr13; - de->media[idx].csr14 = ib->csr14; - de->media[idx].csr15 = ib->csr15; - } + 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"); - de->media[idx].type = idx; - de->media_advertise |= de->media_supported; + 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 @@ 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 @@ 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 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/net/defxx.c linux/drivers/net/defxx.c --- linux-2.5.2-pre6/drivers/net/defxx.c Sun Sep 30 12:26:06 2001 +++ linux/drivers/net/defxx.c Thu Jan 3 14:10:37 2002 @@ -500,7 +500,7 @@ 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 */ diff -urN linux-2.5.2-pre6/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- linux-2.5.2-pre6/drivers/net/irda/irtty.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/net/irda/irtty.c Thu Jan 3 14:10:37 2002 @@ -172,7 +172,7 @@ /* 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 @@ /* 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); /* diff -urN linux-2.5.2-pre6/drivers/net/slip.c linux/drivers/net/slip.c --- linux-2.5.2-pre6/drivers/net/slip.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/net/slip.c Thu Jan 3 14:10:37 2002 @@ -739,7 +739,7 @@ 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 @@ 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 @@ } 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 @@ 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 diff -urN linux-2.5.2-pre6/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c --- linux-2.5.2-pre6/drivers/net/wan/cosa.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/net/wan/cosa.c Thu Jan 3 14:10:37 2002 @@ -940,12 +940,12 @@ 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<= cosa->nchannels) return -ENODEV; chan = cosa->chan + n; diff -urN linux-2.5.2-pre6/drivers/net/wan/sdla_chdlc.c linux/drivers/net/wan/sdla_chdlc.c --- linux-2.5.2-pre6/drivers/net/wan/sdla_chdlc.c Thu Sep 13 16:04:43 2001 +++ linux/drivers/net/wan/sdla_chdlc.c Thu Jan 3 14:10:37 2002 @@ -3933,7 +3933,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h --- linux-2.5.2-pre6/drivers/scsi/BusLogic.h Thu Jul 19 21:07:57 2001 +++ linux/drivers/scsi/BusLogic.h Thu Jan 3 14:10:37 2002 @@ -1531,7 +1531,7 @@ 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 @@ 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); } diff -urN linux-2.5.2-pre6/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- linux-2.5.2-pre6/drivers/scsi/advansys.c Fri Nov 9 14:05:06 2001 +++ linux/drivers/scsi/advansys.c Thu Jan 3 14:10:37 2002 @@ -3610,36 +3610,6 @@ #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 @@ 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 @@ 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 @@ 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 @@ } } - /* - * 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 @@ 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 @@ * 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 @@ 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 @@ /* * 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 @@ /* * Acquire the board lock. */ - spin_lock_irqsave(&boardp->lock, flags); + spin_lock_irqsave(&shp->host_lock, flags); } else { /* @@ -6094,7 +6024,7 @@ * 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 @@ 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 @@ 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 @@ * 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 @@ } } } - spin_unlock_irqrestore(&boardp->lock, flags); + spin_unlock_irqrestore(&shp->host_lock, flags); } /* diff -urN linux-2.5.2-pre6/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- linux-2.5.2-pre6/drivers/scsi/aha152x.c Fri Nov 9 14:05:06 2001 +++ linux/drivers/scsi/aha152x.c Thu Jan 3 14:10:37 2002 @@ -1349,9 +1349,9 @@ 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) { diff -urN linux-2.5.2-pre6/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- linux-2.5.2-pre6/drivers/scsi/aha1740.c Sun Sep 30 12:26:07 2001 +++ linux/drivers/scsi/aha1740.c Thu Jan 3 14:10:37 2002 @@ -213,6 +213,7 @@ /* 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 @@ 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 @@ 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 *)) diff -urN linux-2.5.2-pre6/drivers/scsi/dpt_i2o.c linux/drivers/scsi/dpt_i2o.c --- linux-2.5.2-pre6/drivers/scsi/dpt_i2o.c Wed Nov 28 10:22:27 2001 +++ linux/drivers/scsi/dpt_i2o.c Thu Jan 3 14:10:37 2002 @@ -1157,17 +1157,13 @@ 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 @@ //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 @@ 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 @@ } 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 @@ // 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ 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; } diff -urN linux-2.5.2-pre6/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- linux-2.5.2-pre6/drivers/scsi/eata.c Wed Dec 12 09:20:22 2001 +++ linux/drivers/scsi/eata.c Thu Jan 3 14:10:37 2002 @@ -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. * @@ -223,7 +230,7 @@ * 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 @@ 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 @@ 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 @@ #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 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 @@ 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 @@ } else if (port_base > MAX_ISA_ADDR) { bus_type = "PCI"; + is_pci = TRUE; subversion = ESA; } else { @@ -963,7 +978,13 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ } 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ #else status = DID_BUS_BUSY << 16; #endif + HD(j)->retries++; HD(j)->last_retried_pid = SCpnt->pid; } @@ -2021,6 +2151,8 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/scsi/eata.h linux/drivers/scsi/eata.h --- linux-2.5.2-pre6/drivers/scsi/eata.h Wed Dec 12 09:20:22 2001 +++ linux/drivers/scsi/eata.h Thu Jan 3 14:10:37 2002 @@ -13,7 +13,7 @@ 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 " ", \ diff -urN linux-2.5.2-pre6/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- linux-2.5.2-pre6/drivers/scsi/fdomain.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/scsi/fdomain.c Thu Jan 3 14:10:37 2002 @@ -382,22 +382,23 @@ 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 @@ #if EVERY_ACCESS printk( " AFAIL " ); #endif - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(¤t_SC->host->host_lock, flags); my_done( DID_BUS_BUSY << 16 ); - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(¤t_SC->host->host_lock, flags); return; } current_SC->SCp.phase = in_selection; @@ -1291,9 +1292,9 @@ #if EVERY_ACCESS printk( " SFAIL " ); #endif - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(¤t_SC->host->host_lock, flags); my_done( DID_NO_CONNECT << 16 ); - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(¤t_SC->host->host_lock, flags); return; } else { #if EVERY_ACCESS @@ -1638,10 +1639,10 @@ #if EVERY_ACCESS printk( "BEFORE MY_DONE. . ." ); #endif - spin_lock_irqsave(&io_request_lock, flags); + spin_lock_irqsave(¤t_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(¤t_SC->host->host_lock, flags); #if EVERY_ACCESS printk( "RETURNING.\n" ); #endif @@ -1932,11 +1933,11 @@ 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_16x0_biosparam: too many disks"); return 0; } - drive = MINOR(dev) >> 4; + drive = minor(dev) >> 4; if (bios_major == 2) { switch (Quantum) { diff -urN linux-2.5.2-pre6/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c --- linux-2.5.2-pre6/drivers/scsi/ide-scsi.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/scsi/ide-scsi.c Thu Jan 3 14:10:37 2002 @@ -747,7 +747,7 @@ { 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); } diff -urN linux-2.5.2-pre6/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c --- linux-2.5.2-pre6/drivers/scsi/in2000.c Sun Sep 30 12:26:07 2001 +++ linux/drivers/scsi/in2000.c Thu Jan 3 14:10:37 2002 @@ -855,7 +855,7 @@ /* 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 @@ 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 @@ 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 @@ 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("} ")) /* release the SMP spin_lock and restore irq state */ - CLISPIN_UNLOCK(flags); + CLISPIN_UNLOCK(instance, flags); } diff -urN linux-2.5.2-pre6/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h --- linux-2.5.2-pre6/drivers/scsi/in2000.h Wed Nov 28 10:22:27 2001 +++ linux/drivers/scsi/in2000.h Thu Jan 3 14:10:37 2002 @@ -393,8 +393,9 @@ # 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 *)); diff -urN linux-2.5.2-pre6/drivers/scsi/ips.c linux/drivers/scsi/ips.c --- linux-2.5.2-pre6/drivers/scsi/ips.c Fri Nov 9 14:05:06 2001 +++ linux/drivers/scsi/ips.c Thu Jan 3 14:10:37 2002 @@ -1769,14 +1769,13 @@ 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 @@ /****************************************************************************/ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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 @@ } 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 @@ 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 @@ * 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 @@ clear_bit(IPS_IN_INTR, &ha->flags); - spin_unlock(&io_request_lock); + spin_unlock(&host->host_lock); } udelay(1000); /* 1 milisecond */ diff -urN linux-2.5.2-pre6/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c --- linux-2.5.2-pre6/drivers/scsi/pci2000.c Fri Nov 9 14:05:06 2001 +++ linux/drivers/scsi/pci2000.c Thu Jan 3 14:10:37 2002 @@ -275,11 +275,6 @@ 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 @@ 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 @@ 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 * diff -urN linux-2.5.2-pre6/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c --- linux-2.5.2-pre6/drivers/scsi/pci2220i.c Fri Nov 9 14:05:06 2001 +++ linux/drivers/scsi/pci2220i.c Thu Jan 3 14:10:37 2002 @@ -1152,6 +1152,7 @@ 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 @@ * 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 @@ * 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 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 @@ * 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 @@ * 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 @@ 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 @@ 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 @@ 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 diff -urN linux-2.5.2-pre6/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- linux-2.5.2-pre6/drivers/scsi/scsi.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/scsi/scsi.c Thu Jan 3 14:10:37 2002 @@ -200,13 +200,10 @@ /* 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); diff -urN linux-2.5.2-pre6/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c --- linux-2.5.2-pre6/drivers/scsi/scsi_lib.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/scsi/scsi_lib.c Thu Jan 3 14:10:37 2002 @@ -83,7 +83,6 @@ 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 @@ * 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 @@ * the bad sector. */ SCpnt->request.special = (void *) SCpnt; - __elv_add_request(q, &SCpnt->request, 0, 0); + _elv_add_request(q, &SCpnt->request, 0, 0); } /* diff -urN linux-2.5.2-pre6/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- linux-2.5.2-pre6/drivers/scsi/sg.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/scsi/sg.c Thu Jan 3 14:10:37 2002 @@ -254,7 +254,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/scsi/sim710.c linux/drivers/scsi/sim710.c --- linux-2.5.2-pre6/drivers/scsi/sim710.c Sun Sep 30 12:26:07 2001 +++ linux/drivers/scsi/sim710.c Thu Jan 3 14:10:37 2002 @@ -904,11 +904,12 @@ 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); } diff -urN linux-2.5.2-pre6/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- linux-2.5.2-pre6/drivers/scsi/sr.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/scsi/sr.c Thu Jan 3 14:10:37 2002 @@ -99,11 +99,11 @@ 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 @@ /* 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 @@ * 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 @@ * 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 @@ /* * 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 @@ { 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 @@ * 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 @@ */ 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 @@ 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 @@ * 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 diff -urN linux-2.5.2-pre6/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- linux-2.5.2-pre6/drivers/scsi/sr_ioctl.c Sun Dec 16 12:20:21 2001 +++ linux/drivers/scsi/sr_ioctl.c Thu Jan 3 14:10:37 2002 @@ -68,7 +68,7 @@ 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 @@ 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 @@ /* 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 @@ 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_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 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 @@ 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 @@ 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_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 target; - target = MINOR(cdi->dev); + target = minor(cdi->dev); switch (cmd) { case BLKGETSIZE: diff -urN linux-2.5.2-pre6/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c --- linux-2.5.2-pre6/drivers/scsi/sr_vendor.c Sun Dec 16 12:20:21 2001 +++ linux/drivers/scsi/sr_vendor.c Thu Jan 3 14:10:37 2002 @@ -158,7 +158,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- linux-2.5.2-pre6/drivers/scsi/u14-34f.c Wed Dec 12 09:20:22 2001 +++ linux/drivers/scsi/u14-34f.c Thu Jan 3 14:10:37 2002 @@ -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. * @@ -186,7 +193,7 @@ * * 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 @@ #include "u14-34f.h" #include #include +#include #include #include #include @@ -483,13 +491,13 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ } 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 @@ 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 @@ } 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h --- linux-2.5.2-pre6/drivers/scsi/u14-34f.h Wed Dec 12 09:20:22 2001 +++ linux/drivers/scsi/u14-34f.h Thu Jan 3 14:10:37 2002 @@ -13,7 +13,7 @@ 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 " ", \ diff -urN linux-2.5.2-pre6/drivers/sound/cs4281/cs4281m.c linux/drivers/sound/cs4281/cs4281m.c --- linux-2.5.2-pre6/drivers/sound/cs4281/cs4281m.c Sun Sep 30 12:26:08 2001 +++ linux/drivers/sound/cs4281/cs4281m.c Thu Jan 3 14:10:37 2002 @@ -2569,7 +2569,7 @@ 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_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 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) diff -urN linux-2.5.2-pre6/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c --- linux-2.5.2-pre6/drivers/sound/cs46xx.c Sun Sep 30 12:26:08 2001 +++ linux/drivers/sound/cs46xx.c Thu Jan 3 14:10:37 2002 @@ -1835,7 +1835,7 @@ 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 @@ 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 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_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; diff -urN linux-2.5.2-pre6/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- linux-2.5.2-pre6/drivers/sound/es1370.c Sun Sep 30 12:26:08 2001 +++ linux/drivers/sound/es1370.c Thu Jan 3 14:10:37 2002 @@ -1029,7 +1029,7 @@ 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_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_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 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; diff -urN linux-2.5.2-pre6/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- linux-2.5.2-pre6/drivers/sound/esssolo1.c Sun Sep 30 12:26:08 2001 +++ linux/drivers/sound/esssolo1.c Thu Jan 3 14:10:37 2002 @@ -913,7 +913,7 @@ 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_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 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_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; diff -urN linux-2.5.2-pre6/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- linux-2.5.2-pre6/drivers/sound/i810_audio.c Fri Nov 9 14:07:41 2001 +++ linux/drivers/sound/i810_audio.c Thu Jan 3 14:10:37 2002 @@ -2345,7 +2345,7 @@ 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) diff -urN linux-2.5.2-pre6/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- linux-2.5.2-pre6/drivers/sound/maestro.c Sun Sep 30 12:26:08 2001 +++ linux/drivers/sound/maestro.c Thu Jan 3 14:10:37 2002 @@ -2126,7 +2126,7 @@ /* --------------------------------------------------------------------- */ 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 @@ 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; diff -urN linux-2.5.2-pre6/drivers/sound/maestro3.c linux/drivers/sound/maestro3.c --- linux-2.5.2-pre6/drivers/sound/maestro3.c Sun Nov 25 10:17:47 2001 +++ linux/drivers/sound/maestro3.c Thu Jan 3 14:10:37 2002 @@ -1969,7 +1969,7 @@ 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 @@ /* 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) { diff -urN linux-2.5.2-pre6/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- linux-2.5.2-pre6/drivers/sound/soundcard.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/sound/soundcard.c Thu Jan 3 14:10:37 2002 @@ -144,7 +144,7 @@ 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_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 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_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 @@ 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 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 @@ 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; diff -urN linux-2.5.2-pre6/drivers/usb/Config.in linux/drivers/usb/Config.in --- linux-2.5.2-pre6/drivers/usb/Config.in Sat Dec 8 20:28:44 2001 +++ linux/drivers/usb/Config.in Thu Jan 3 14:10:37 2002 @@ -18,7 +18,8 @@ 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 @@ 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 diff -urN linux-2.5.2-pre6/drivers/usb/Makefile linux/drivers/usb/Makefile --- linux-2.5.2-pre6/drivers/usb/Makefile Fri Oct 5 12:04:51 2001 +++ linux/drivers/usb/Makefile Thu Jan 3 14:10:37 2002 @@ -10,19 +10,13 @@ # 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_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,9 +75,15 @@ 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 diff -urN linux-2.5.2-pre6/drivers/usb/acm.c linux/drivers/usb/acm.c --- linux-2.5.2-pre6/drivers/usb/acm.c Fri Oct 5 12:06:08 2001 +++ linux/drivers/usb/acm.c Thu Jan 3 14:10:37 2002 @@ -297,7 +297,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/usb/audio.c linux/drivers/usb/audio.c --- linux-2.5.2-pre6/drivers/usb/audio.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/usb/audio.c Thu Jan 3 14:10:37 2002 @@ -1947,7 +1947,7 @@ 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_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; diff -urN linux-2.5.2-pre6/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- linux-2.5.2-pre6/drivers/usb/bluetooth.c Sat Dec 8 20:28:44 2001 +++ linux/drivers/usb/bluetooth.c Thu Jan 3 14:10:37 2002 @@ -360,7 +360,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c --- linux-2.5.2-pre6/drivers/usb/dabusb.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/usb/dabusb.c Thu Jan 3 14:10:37 2002 @@ -579,7 +579,7 @@ 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)) diff -urN linux-2.5.2-pre6/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c --- linux-2.5.2-pre6/drivers/usb/dc2xx.c Sat Dec 8 20:28:45 2001 +++ linux/drivers/usb/dc2xx.c Thu Jan 3 14:10:37 2002 @@ -298,7 +298,7 @@ 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); diff -urN linux-2.5.2-pre6/drivers/usb/hcd/Config.in linux/drivers/usb/hcd/Config.in --- linux-2.5.2-pre6/drivers/usb/hcd/Config.in Thu Jan 3 14:10:33 2002 +++ linux/drivers/usb/hcd/Config.in Thu Jan 3 14:10:37 2002 @@ -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 diff -urN linux-2.5.2-pre6/drivers/usb/hiddev.c linux/drivers/usb/hiddev.c --- linux-2.5.2-pre6/drivers/usb/hiddev.c Fri Nov 30 08:26:04 2001 +++ linux/drivers/usb/hiddev.c Thu Jan 3 14:10:38 2002 @@ -218,7 +218,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/usb/printer.c linux/drivers/usb/printer.c --- linux-2.5.2-pre6/drivers/usb/printer.c Tue Oct 9 15:15:02 2001 +++ linux/drivers/usb/printer.c Thu Jan 3 14:10:38 2002 @@ -201,7 +201,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- linux-2.5.2-pre6/drivers/usb/scanner.c Sat Dec 8 20:28:44 2001 +++ linux/drivers/usb/scanner.c Thu Jan 3 14:10:38 2002 @@ -365,7 +365,7 @@ struct scn_usb_data *scn; struct usb_device *dev; - kdev_t scn_minor; + int scn_minor; int err=0; @@ -432,7 +432,7 @@ { struct scn_usb_data *scn; - kdev_t scn_minor; + int scn_minor; scn_minor = USB_SCN_MINOR (inode); @@ -469,7 +469,7 @@ 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 @@ 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 @@ { struct usb_device *dev; - kdev_t scn_minor; + int scn_minor; scn_minor = USB_SCN_MINOR(inode); @@ -810,8 +809,7 @@ 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; diff -urN linux-2.5.2-pre6/drivers/usb/scanner.h linux/drivers/usb/scanner.h --- linux-2.5.2-pre6/drivers/usb/scanner.h Sat Dec 8 20:28:44 2001 +++ linux/drivers/usb/scanner.h Thu Jan 3 14:10:38 2002 @@ -203,7 +203,7 @@ #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 @@ 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 */ diff -urN linux-2.5.2-pre6/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in --- linux-2.5.2-pre6/drivers/usb/serial/Config.in Wed Oct 17 14:35:17 2001 +++ linux/drivers/usb/serial/Config.in Thu Jan 3 14:10:38 2002 @@ -15,6 +15,7 @@ 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_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 diff -urN linux-2.5.2-pre6/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- linux-2.5.2-pre6/drivers/usb/serial/Makefile Tue Oct 9 15:15:02 2001 +++ linux/drivers/usb/serial/Makefile Thu Jan 3 14:10:38 2002 @@ -8,6 +8,7 @@ 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_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 diff -urN linux-2.5.2-pre6/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- linux-2.5.2-pre6/drivers/usb/serial/usbserial.c Sat Dec 8 20:28:45 2001 +++ linux/drivers/usb/serial/usbserial.c Thu Jan 3 14:10:38 2002 @@ -397,16 +397,16 @@ 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 @@ { struct usb_serial *serial; struct usb_serial_port *port; - int portNumber; + unsigned int portNumber; dbg(__FUNCTION__); @@ -513,14 +513,14 @@ 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 -urN linux-2.5.2-pre6/drivers/usb/stv680.c linux/drivers/usb/stv680.c --- linux-2.5.2-pre6/drivers/usb/stv680.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/stv680.c Thu Jan 3 14:10:38 2002 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 " +#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 +*/ + +#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 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> 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 -urN linux-2.5.2-pre6/drivers/usb/stv680.h linux/drivers/usb/stv680.h --- linux-2.5.2-pre6/drivers/usb/stv680.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/stv680.h Thu Jan 3 14:10:38 2002 @@ -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 -urN linux-2.5.2-pre6/drivers/usb/vicam.c linux/drivers/usb/vicam.c --- linux-2.5.2-pre6/drivers/usb/vicam.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/vicam.c Thu Jan 3 14:10:38 2002 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "vicam.h" +#include "vicamurbs.h" + +/* Version Information */ +#define DRIVER_VERSION "v0" +#define DRIVER_AUTHOR "Christopher L Cheney , Pavel Machek " +#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; ioffsets[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 -urN linux-2.5.2-pre6/drivers/usb/vicam.h linux/drivers/usb/vicam.h --- linux-2.5.2-pre6/drivers/usb/vicam.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/vicam.h Thu Jan 3 14:10:38 2002 @@ -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 -urN linux-2.5.2-pre6/drivers/usb/vicamurbs.h linux/drivers/usb/vicamurbs.h --- linux-2.5.2-pre6/drivers/usb/vicamurbs.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/vicamurbs.h Thu Jan 3 14:10:38 2002 @@ -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 diff -urN linux-2.5.2-pre6/drivers/video/fbcon.c linux/drivers/video/fbcon.c --- linux-2.5.2-pre6/drivers/video/fbcon.c Mon Oct 15 13:47:13 2001 +++ linux/drivers/video/fbcon.c Thu Jan 3 14:10:38 2002 @@ -271,10 +271,10 @@ /* 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; } diff -urN linux-2.5.2-pre6/drivers/video/fbmem.c linux/drivers/video/fbmem.c --- linux-2.5.2-pre6/drivers/video/fbmem.c Thu Jan 3 14:10:33 2002 +++ linux/drivers/video/fbmem.c Thu Jan 3 14:10:38 2002 @@ -625,7 +625,7 @@ #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 @@ 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; diff -urN linux-2.5.2-pre6/drivers/video/vesafb.c linux/drivers/video/vesafb.c --- linux-2.5.2-pre6/drivers/video/vesafb.c Wed Nov 14 14:52:20 2001 +++ linux/drivers/video/vesafb.c Thu Jan 3 14:10:38 2002 @@ -648,7 +648,7 @@ 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; diff -urN linux-2.5.2-pre6/fs/affs/super.c linux/fs/affs/super.c --- linux-2.5.2-pre6/fs/affs/super.c Thu Jan 3 14:10:33 2002 +++ linux/fs/affs/super.c Thu Jan 3 14:10:38 2002 @@ -262,7 +262,7 @@ * 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; diff -urN linux-2.5.2-pre6/fs/coda/inode.c linux/fs/coda/inode.c --- linux-2.5.2-pre6/fs/coda/inode.c Thu Jan 3 14:10:33 2002 +++ linux/fs/coda/inode.c Thu Jan 3 14:10:38 2002 @@ -70,7 +70,7 @@ 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 @@ return -1; } - idx = MINOR(inode->i_rdev); + idx = minor(inode->i_rdev); fput(file); if(idx < 0 || idx >= MAX_CODADEVS) { diff -urN linux-2.5.2-pre6/fs/cramfs/inode.c linux/fs/cramfs/inode.c --- linux-2.5.2-pre6/fs/cramfs/inode.c Thu Jan 3 14:10:33 2002 +++ linux/fs/cramfs/inode.c Thu Jan 3 14:10:38 2002 @@ -115,7 +115,7 @@ 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 @@ } 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; diff -urN linux-2.5.2-pre6/fs/devfs/base.c linux/fs/devfs/base.c --- linux-2.5.2-pre6/fs/devfs/base.c Thu Jan 3 14:10:33 2002 +++ linux/fs/devfs/base.c Thu Jan 3 14:10:38 2002 @@ -1063,16 +1063,16 @@ 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 @@ 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 ) { diff -urN linux-2.5.2-pre6/fs/devfs/util.c linux/fs/devfs/util.c --- linux-2.5.2-pre6/fs/devfs/util.c Thu Jan 3 14:10:33 2002 +++ linux/fs/devfs/util.c Thu Jan 3 14:10:38 2002 @@ -320,8 +320,8 @@ 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) { diff -urN linux-2.5.2-pre6/fs/dquot.c linux/fs/dquot.c --- linux-2.5.2-pre6/fs/dquot.c Thu Jan 3 14:10:33 2002 +++ linux/fs/dquot.c Thu Jan 3 14:10:38 2002 @@ -1483,7 +1483,7 @@ 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: diff -urN linux-2.5.2-pre6/fs/ext3/ialloc.c linux/fs/ext3/ialloc.c --- linux-2.5.2-pre6/fs/ext3/ialloc.c Sun Dec 16 12:23:00 2001 +++ linux/fs/ext3/ialloc.c Thu Jan 3 14:10:38 2002 @@ -189,7 +189,7 @@ 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; } diff -urN linux-2.5.2-pre6/fs/ext3/super.c linux/fs/ext3/super.c --- linux-2.5.2-pre6/fs/ext3/super.c Thu Jan 3 14:10:33 2002 +++ linux/fs/ext3/super.c Thu Jan 3 14:10:38 2002 @@ -389,8 +389,8 @@ 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 @@ 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 @@ 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_dev_journal(struct super_block *sb, - int dev) + kdev_t j_dev) { struct buffer_head * bh; journal_t *journal; @@ -1268,16 +1268,15 @@ 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 @@ 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 @@ 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 @@ { 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 @@ } } - 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; diff -urN linux-2.5.2-pre6/fs/hfs/file.c linux/fs/hfs/file.c --- linux-2.5.2-pre6/fs/hfs/file.c Thu Jan 3 14:10:33 2002 +++ linux/fs/hfs/file.c Thu Jan 3 14:10:38 2002 @@ -310,8 +310,8 @@ 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; diff -urN linux-2.5.2-pre6/fs/intermezzo/psdev.c linux/fs/intermezzo/psdev.c --- linux-2.5.2-pre6/fs/intermezzo/psdev.c Thu Jan 3 14:10:33 2002 +++ linux/fs/intermezzo/psdev.c Thu Jan 3 14:10:38 2002 @@ -78,12 +78,12 @@ { 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; diff -urN linux-2.5.2-pre6/fs/intermezzo/super.c linux/fs/intermezzo/super.c --- linux-2.5.2-pre6/fs/intermezzo/super.c Sun Nov 11 10:20:21 2001 +++ linux/fs/intermezzo/super.c Thu Jan 3 14:10:38 2002 @@ -159,7 +159,7 @@ { struct nameidata nd; struct dentry *dentry; - kdev_t devno = 0; + kdev_t devno = NODEV; int error; ENTRY; @@ -188,19 +188,19 @@ } 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; } diff -urN linux-2.5.2-pre6/fs/jffs/inode-v23.c linux/fs/jffs/inode-v23.c --- linux-2.5.2-pre6/fs/jffs/inode-v23.c Thu Jan 3 14:10:33 2002 +++ linux/fs/jffs/inode-v23.c Thu Jan 3 14:10:38 2002 @@ -81,7 +81,7 @@ 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; diff -urN linux-2.5.2-pre6/fs/jffs2/dir.c linux/fs/jffs2/dir.c --- linux-2.5.2-pre6/fs/jffs2/dir.c Fri Sep 14 14:04:07 2001 +++ linux/fs/jffs2/dir.c Thu Jan 3 14:10:38 2002 @@ -795,7 +795,7 @@ 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); } diff -urN linux-2.5.2-pre6/fs/jffs2/file.c linux/fs/jffs2/file.c --- linux-2.5.2-pre6/fs/jffs2/file.c Thu Oct 4 15:13:18 2001 +++ linux/fs/jffs2/file.c Thu Jan 3 14:10:38 2002 @@ -105,8 +105,8 @@ 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)); diff -urN linux-2.5.2-pre6/fs/jffs2/gc.c linux/fs/jffs2/gc.c --- linux-2.5.2-pre6/fs/jffs2/gc.c Thu Oct 4 15:13:18 2001 +++ linux/fs/jffs2/gc.c Thu Jan 3 14:10:38 2002 @@ -269,8 +269,8 @@ 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)); diff -urN linux-2.5.2-pre6/fs/jffs2/super.c linux/fs/jffs2/super.c --- linux-2.5.2-pre6/fs/jffs2/super.c Thu Oct 4 15:14:35 2001 +++ linux/fs/jffs2/super.c Thu Jan 3 14:10:38 2002 @@ -199,7 +199,7 @@ 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; diff -urN linux-2.5.2-pre6/fs/namei.c linux/fs/namei.c --- linux-2.5.2-pre6/fs/namei.c Thu Jan 3 14:10:33 2002 +++ linux/fs/namei.c Thu Jan 3 14:10:38 2002 @@ -1589,7 +1589,7 @@ 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 @@ 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 @@ 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) diff -urN linux-2.5.2-pre6/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- linux-2.5.2-pre6/fs/ncpfs/inode.c Sun Sep 30 12:26:08 2001 +++ linux/fs/ncpfs/inode.c Thu Jan 3 14:10:38 2002 @@ -181,7 +181,7 @@ 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; diff -urN linux-2.5.2-pre6/fs/nfs/write.c linux/fs/nfs/write.c --- linux-2.5.2-pre6/fs/nfs/write.c Thu Jan 3 14:10:33 2002 +++ linux/fs/nfs/write.c Thu Jan 3 14:10:38 2002 @@ -1201,8 +1201,9 @@ 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)); diff -urN linux-2.5.2-pre6/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c --- linux-2.5.2-pre6/fs/nfsd/nfs3xdr.c Wed Oct 3 22:27:48 2001 +++ linux/fs/nfsd/nfs3xdr.c Thu Jan 3 14:10:38 2002 @@ -173,9 +173,9 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/fs/partitions/acorn.c linux/fs/partitions/acorn.c --- linux-2.5.2-pre6/fs/partitions/acorn.c Tue Dec 11 09:44:13 2001 +++ linux/fs/partitions/acorn.c Thu Jan 3 14:10:38 2002 @@ -28,7 +28,7 @@ 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); } diff -urN linux-2.5.2-pre6/fs/partitions/ibm.c linux/fs/partitions/ibm.c --- linux-2.5.2-pre6/fs/partitions/ibm.c Mon Oct 1 20:03:26 2001 +++ linux/fs/partitions/ibm.c Thu Jan 3 14:10:38 2002 @@ -125,7 +125,7 @@ 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; } diff -urN linux-2.5.2-pre6/fs/romfs/inode.c linux/fs/romfs/inode.c --- linux-2.5.2-pre6/fs/romfs/inode.c Thu Jan 3 14:10:33 2002 +++ linux/fs/romfs/inode.c Thu Jan 3 14:10:38 2002 @@ -518,7 +518,9 @@ 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); } } diff -urN linux-2.5.2-pre6/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog --- linux-2.5.2-pre6/fs/smbfs/ChangeLog Tue Oct 2 17:03:34 2001 +++ linux/fs/smbfs/ChangeLog Thu Jan 3 14:10:38 2002 @@ -1,5 +1,15 @@ ChangeLog for smbfs. +2001-12-31 René Scharfe + + * 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 + + * file.c, proc.c: Fix problems triggered by the "fsx test" + 2001-09-17 Urban Widmark * proc.c: Use 4096 (was 512) as the blocksize for better write diff -urN linux-2.5.2-pre6/fs/smbfs/file.c linux/fs/smbfs/file.c --- linux-2.5.2-pre6/fs/smbfs/file.c Tue Oct 2 17:03:34 2001 +++ linux/fs/smbfs/file.c Thu Jan 3 14:10:38 2002 @@ -270,7 +270,6 @@ static int smb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { - kmap(page); return 0; } @@ -283,7 +282,6 @@ lock_kernel(); status = smb_updatepage(file, page, offset, to-offset); unlock_kernel(); - kunmap(page); return status; } @@ -349,8 +347,14 @@ 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; } diff -urN linux-2.5.2-pre6/fs/smbfs/getopt.c linux/fs/smbfs/getopt.c --- linux-2.5.2-pre6/fs/smbfs/getopt.c Fri Apr 27 14:10:32 2001 +++ linux/fs/smbfs/getopt.c Thu Jan 3 14:10:38 2002 @@ -46,7 +46,7 @@ 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; diff -urN linux-2.5.2-pre6/fs/smbfs/getopt.h linux/fs/smbfs/getopt.h --- linux-2.5.2-pre6/fs/smbfs/getopt.h Mon Aug 14 13:31:10 2000 +++ linux/fs/smbfs/getopt.h Thu Jan 3 14:10:38 2002 @@ -3,7 +3,6 @@ struct option { const char *name; - int has_arg; unsigned long flag; int val; }; diff -urN linux-2.5.2-pre6/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- linux-2.5.2-pre6/fs/smbfs/inode.c Tue Oct 2 17:03:34 2001 +++ linux/fs/smbfs/inode.c Thu Jan 3 14:10:38 2002 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -41,9 +42,12 @@ #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 @@ delete_inode: smb_delete_inode, put_super: smb_put_super, statfs: smb_statfs, + show_options: smb_show_options, }; @@ -259,21 +264,20 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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; diff -urN linux-2.5.2-pre6/fs/umsdos/inode.c linux/fs/umsdos/inode.c --- linux-2.5.2-pre6/fs/umsdos/inode.c Sun Sep 30 12:26:08 2001 +++ linux/fs/umsdos/inode.c Thu Jan 3 14:10:38 2002 @@ -49,7 +49,7 @@ 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 @@ * 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; /* diff -urN linux-2.5.2-pre6/include/linux/blk.h linux/include/linux/blk.h --- linux-2.5.2-pre6/include/linux/blk.h Thu Jan 3 14:10:33 2002 +++ linux/include/linux/blk.h Thu Jan 3 14:10:38 2002 @@ -2,6 +2,7 @@ #define _BLK_H #include +#include #include #include #include @@ -43,9 +44,10 @@ 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 @@ 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) diff -urN linux-2.5.2-pre6/include/linux/blkdev.h linux/include/linux/blkdev.h --- linux-2.5.2-pre6/include/linux/blkdev.h Thu Jan 3 14:10:33 2002 +++ linux/include/linux/blkdev.h Thu Jan 3 14:10:38 2002 @@ -25,7 +25,7 @@ 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]; diff -urN linux-2.5.2-pre6/include/linux/elevator.h linux/include/linux/elevator.h --- linux-2.5.2-pre6/include/linux/elevator.h Thu Jan 3 14:10:33 2002 +++ linux/include/linux/elevator.h Thu Jan 3 14:10:38 2002 @@ -11,36 +11,53 @@ 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 *); - -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 *); +/* + * 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; + +/* + * 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 @@ #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 diff -urN linux-2.5.2-pre6/include/linux/ide.h linux/include/linux/ide.h --- linux-2.5.2-pre6/include/linux/ide.h Thu Jan 3 14:10:33 2002 +++ linux/include/linux/ide.h Thu Jan 3 14:10:38 2002 @@ -917,6 +917,12 @@ 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. */ diff -urN linux-2.5.2-pre6/include/linux/sched.h linux/include/linux/sched.h --- linux-2.5.2-pre6/include/linux/sched.h Thu Jan 3 14:10:33 2002 +++ linux/include/linux/sched.h Thu Jan 3 14:10:38 2002 @@ -302,7 +302,7 @@ * 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 list_head run_list; long time_slice; - unsigned long sleep_time; /* recalculation loop checkpoint */ unsigned long rcl_last; @@ -453,7 +452,7 @@ */ #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 @@ 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; } diff -urN linux-2.5.2-pre6/kernel/device.c linux/kernel/device.c --- linux-2.5.2-pre6/kernel/device.c Mon Dec 10 14:15:12 2001 +++ linux/kernel/device.c Thu Jan 3 14:10:38 2002 @@ -732,15 +732,10 @@ 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 @@ 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); diff -urN linux-2.5.2-pre6/kernel/sched.c linux/kernel/sched.c --- linux-2.5.2-pre6/kernel/sched.c Thu Jan 3 14:10:33 2002 +++ linux/kernel/sched.c Thu Jan 3 14:10:38 2002 @@ -51,11 +51,11 @@ * 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 @@ 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 @@ 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 @@ { 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) diff -urN linux-2.5.2-pre6/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c --- linux-2.5.2-pre6/net/irda/ircomm/ircomm_tty.c Thu Jan 3 14:10:33 2002 +++ linux/net/irda/ircomm/ircomm_tty.c Thu Jan 3 14:10:38 2002 @@ -386,13 +386,13 @@ 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; diff -urN linux-2.5.2-pre6/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c --- linux-2.5.2-pre6/net/netlink/netlink_dev.c Fri Nov 9 14:12:55 2001 +++ linux/net/netlink/netlink_dev.c Thu Jan 3 14:10:38 2002 @@ -41,7 +41,7 @@ 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 @@ 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 @@ 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 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 @@ 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_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)